React is for beginners
Introduce
This article introduces the general React concepts that I have explored and referenced in the internet, with the aim of helping people who are starting to learn about React.
- React works well as a View Layer
React is not the same as the MVC framework or javascript frameworks that you know from the past. Simply, it is a library that helps users make creating View easier. - Build components in small-scale applications
For developers, breaking down classes, modules are easier to understand, test, maintain, and this is also true of components in React. Of course, the exact size will depend on many different factors. (include your personal preference!) For example:
1 2 3 4 5 6 7 8 | const LatestPostsComponent = props => ( <section> <div> <h1> Latest posts </h1> </div> <div> {props.posts.map (post => <PostPreview key = {post.slug} post = {post} />)} </div> </section> ); |
3. Function Component
There are 2 ways to write functions for component, 1 is to write React.createClass ()
1 2 3 4 5 | const MyComponent = React.createClass ({ render: function () { return <div className = {this.props.className} />; } }); |
and the second way is to write in ES6 format
1 2 3 4 5 | class MyComponent extends React.Component { render () { return <div className = {this.props.className} />; } } |
React 0.14 introduced a new structure for components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | const LatestPostsComponent = props => { const postPreviews = renderPostPreviews (props.posts); return ( <section> <div> <h1> Latest posts </h1> </div> <div> {postPreviews} </div> </section> ); }; const renderPostPreviews = posts => ( posts.map (post => this.renderPostPreview (post)) ); const renderPostPreview = post => ( <article> <h3> <a href={`/post/${post.slug}`}> {post.title} </a> </h3> <time pubdate> <em> {post.posted} </em> </time> <div> <span> {post.blurb} </span> <a href={`/post/${post.slug}`}> Read more ... </a> </div> </article> ); |
4. Use propTypes
propTypes helps developers easily create more secure components, and it will look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | const ListOfNumbers = props => ( <ol className = {props.className}> { props.numbers.map (number => ( <li> {number} </li>) ) } </ol> ); ListOfNumbers.propTypes = { className: React.PropTypes.string.isRequired, numbers: React.PropTypes.arrayOf (React.PropTypes.number) }; |
- Some benefits of using propTypes:
- It is easy to catch errors easily
- If you use the isRequired attribute, there is no need to perform an undeined or null check in the code
- 5. Implement unit test for React
- Drawing from many documents, I found three ways to implement unit tests for components:
- Render logic
For example, by displaying an image or with loading icon, we do the following:
1 2 3 4 5 6 7 | const Image = props => { if (props.loading) { return <LoadingIcon />; } return <img src = {props.src} />; }; |
then we will perform the test as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 | describe ('Image', () => { it ('renders a loading icon when the image is loading', () => { const image = shallowRender (<Image loading = {true} />); expect (image.type) .toEqual (LoadingIcon); }); it ('renders the image once it has loaded', () => { const image = shallowRender (<Image loading = {false} src = "https://example.com/image.jpg" />); expect (image.type) .toEqual ('img'); }); }); |
Transform the Prop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const TextWithArrayOfClassNames = props => ( <div> <p className = {props.classNames.join ('')}> {props.text} </p> </div> ); describe ('TextWithArrayOfClassNames', () => { it ('đang chuyển đổi mảng vào một bảng phân vùng', () => { const text = 'Hello, world!'; const classNames = ['red', 'bold', 'float-right']; const textWithArrayOfClassNames = shallowRender (<TextWithArrayOfClassNames text = {text} classNames = {classNames} />); const childClassNames = textWithArrayOfClassNames.props.children.props.className; expect (childClassNames) .toEqual ('red bold float-right'); }); }); |
Interaction with users
Of course, components are not just for display, they are also used for interaction:
1 2 3 | const RedInput = props => ( <input className = "red" onChange = {props.onChange} /> ) |
Here's my favorite way to test:
1 2 3 4 5 6 7 8 9 | describe ('RedInput', () => { it ('passes events to callback đưa ra khi giá trị thay đổi', () => { const callback = jasmine.createSpy (); const redInput = shallowRender (<RedInput onChange = {callback} />); redInput.props.onChange ('an event!'); expect (callback) .toHaveBeenCalledWith ('an event!'); }); }); |