- Learning react.js is easier than you think
- By Samer Buna
- Translation from: The Gold Project
- This article is permalink: github.com/xitu/gold-m…
- Translator: Cherry
- Proofreader: LeviDing, undead25
Learning React.js is easier than you might think
Learn the basic principles of React.js through an article in Medium
Have you ever noticed that there’s a six-pointed star hidden in the React logo? Just by the way… Last year I wrote a short book about learning React.js, about 100 pages long. This year, I challenged myself to sum it up into an essay and submit it to Medium.
This article is not about what is React or how you should learn React. This is an introduction to the fundamentals of React.js for those who are already familiar with the JavaScript and DOM apis
This article uses an embedded jsComplete code section, so you’ll need a proper screen width for easy reading.
All of the code below is for reference only. They are also examples provided purely to express concepts. Most of them have better practices.
You can edit and execute any of the code snippets below. Ctrl+Enter to execute the code. In the lower right corner of each paragraph is a link to edit or run the code in full-screen mode at jsComplete/repl when clicked.
1 React is all componentized
React is designed around the concept of reusable components. You define small pieces and combine them to form larger components.
Regardless of size, all components are reusable, even across different projects.
In its simplest form, the React component is a plain JavaScript function:
function Button (props) {
// Return a DOM element, for example:
return <button type="submit">{props.label}</button>;
}
// Render the button component to the browser
ReactDOM.render(<Button label="Save" />, mountNode)Copy the code
Example 1: Edit the code above and press Ctrl+Enter to execute.
The button tag in parentheses is explained later. Don’t worry about them now. ReactDOM will also be explained later, but the render function above is required if you want to test this and all subsequent examples. React will take over and control the second parameter of reactdom. render, which is the target DOM element. In jsComplete REPL, you can use the special variable mountNode.
Note to Example 1:
- Capitalize the first letter of the component name,
Button
. This is necessary because we will be dealing with a mixture of HTML elements and React elements. Lowercase names are reserved for HTML elements. In fact, name the React component “Button” and you’ll notice that ReactDOM will ignore this function and just render it as a normal empty HTML button. - Each component receives a list of attributes, just like an HTML element. In React, this list is called properties. You can call a function whatever you want, though.
- In the return output of the Button function component above, we have oddly written a section of code that looks like HTML. This is actually neither JavaScript nor HTML, and honestly, it’s not even react.js. However, it’s so popular that it’s the default in the React app. This is called JSX, which is an extension to JavaScript. JSX is also a compromise! Go ahead and return the other HTML elements in the above function to see how they are supported (for example, return a text input element).
2 What does JSX output?
Example 1 above can be written with pure react.js without JSX, as follows:
function Button (props) {
return React.createElement(
"button",
{ type: "submit" },
props.label
);
}
// To use Button, you can do this
ReactDOM.render(
React.createElement(Button, { label: "Save" }),
mountNode
);Copy the code
Example 2: Write the React component without JSX
In the React top-level API, the createElement function is the main function. This is one of the seven apis you need to learn. That’s how small the React API is.
Just as DOM itself has a document.createElement function to create an element specified by the tag name, React’s createElement function is a high-level function that has the same functionality as document.createElement. But it can also be used to create an element that represents the React component. When we use the button component in Example 2 above, we use the latter.
Unlike Document. createElement, React createElement receives a dynamic parameter after the second parameter, which represents the child element of the created element. So createElement actually creates a tree.
Here’s an example:
const InputForm = React.createElement(
"form",
{ target: "_blank".action: "https://google.com/search" },
React.createElement("div".null."Enter input and click Search"),
React.createElement("input", { className: "big-input" }),
React.createElement(Button, { label: "Search"}));// InputForm uses the Button component, so we need to do this:
function Button (props) {
return React.createElement(
"button",
{ type: "submit" },
props.label
);
}
// Then we can use the InputForm directly with the.render method
ReactDOM.render(InputForm, mountNode);Copy the code
Example 3: React creates the element API
A few things to note in the above example:
InputForm
Not a React component; It’s just a ReactThe element. That’s why we can be hereReactDOM.render
And can be invoked without using it<InputForm />
The reason why.- The React. CreateElement function takes multiple arguments after the first two. The list of parameters starting with the third parameter constitutes the list of children of the created element.
- We can nest
React.createElement
Because it’s JavaScript. - When the element does not require attributes, the second argument to React. CreateElement can be null or an empty object.
- We can mix HTML elements in the React component. You can use HTML elements as built-in React components.
- The React API tries to be the same as the DOM API, which is why we use it in the input element, right
className
Instead ofclass
The reason why. We all wish the React API was part of the DOM API itself, because, you know, it’s so much better.
The code above is how the browser interprets it when you introduce the React library. The browser does not handle any JSX business. However, we prefer to see and use HTML over those createElement calls (imagine building a website with document.CreateElement only!). . That’s why JSX exists. Instead of calling React. CreateElement, we can use a very simple HTML-like syntax:
constInputForm = <form target="_blank" action="https://google.com/search"> <div>Enter input and click Search</div> <input className="big-input" name="q" /> <Button label="Search" /> </form>; // The InputForm "still" uses the Button component, so we need to do the same. Function Button (props) {// Return a DOM element here. For example: return <button type="submit">{props. Label}</button>; } // Then we can use InputForm ReactDOM. Render (InputForm, mountNode);Copy the code
Example 4: Why JSX is popular in React (compared to Example 3)
Note a few things above:
- This is not HTML code. For example, we can still use
className
Instead ofclass
. - We’re still figuring out how to make the above JavaScript look like HTML. Let’s see how I added it at the end.
What we wrote above (example 4) is JSX. However, we will give the compiled version (example 3) to the browser. To do this, we need to use a preprocessor to convert the JSX version to the React. CreateElement version.
This is JSX. This is a compromise that allows us to write our React components in AN HTML-like syntax, which is a good way to do it.
“Flux” is used in the head as a rhyme, but it is also a very popular application architecture, popularized by Facebook. The most famous ones are Redux, Flux and React are very suitable.
JSX, which can be used on its own, doesn’t just work with React.
You can use JSX anywhere in JavaScript
In JSX, you can use any JavaScript expression within a pair of curly braces.
const RandomValue = () => <div> { Math.floor(Math.random() * 100) } </div>; // Use: reactdom.render (<RandomValue />, mountNode);Copy the code
Example 5: Using JavaScript expressions in JSX
Any JavaScript expression can be placed directly inside curly braces. This is equivalent to inserting the ${} template into JavaScript.
This is the only constraint in JSX: there are only expressions. For example, you can’t use if statements, but ternary expressions can.
JavaScript variables are also expressions, so when a component accepts a list of properties (excluding the RandomValue component, props is optional), you can use those properties inside curly braces. This is how we used the Button component above (example 1).
JavaScript objects are also expressions. Sometimes we use JavaScript objects inside curly braces. It looks like we’re using two curly braces, but there’s really only one object inside curly braces. One such use case is to pass a CSS style object to a particular style property in the response:
const ErrorDisplay = ({message}) =>
<div style={ { color: 'red', backgroundColor: 'yellow' } }>
{message}
</div>;
// 使用
ReactDOM.render(
<ErrorDisplay
message="These aren't the droids you're looking for"
/>,
mountNode
);Copy the code
Example 6: An object passes a special React style parameter
Note that I only deconstruct the information outside of the property parameters. This is just JavaScript. Also note that the style attribute above is a special attribute (again, it’s not HTML, it’s closer to the DOM API). We use an object as the value of the style property and that object defines the style just as we would with JavaScript (we can do this).
You can use React elements in JSX. Because this is also an expression (remember, a React element is just a function call) :
const MaybeError = ({errorMessage}) => <div> {errorMessage && <ErrorDisplay message={errorMessage} />} </div>; Const ErrorDisplay = ({message}) => <div style={{color: 'red', backgroundColor: 'yellow' } }> {message} </div>; // Now we use the MaybeError component: reactdom.render (<MaybeError errorMessage={math.random () > 0.5? 'Not good' : ''} />, mountNode );Copy the code
Example 7: A React element is an expression that can be used with {}
The MaybeError component above will only display the ErrorDisplay component if there is an errorMessage passed in or if there is another empty div. React considers {true}, {false} {undefined}, and {null} valid elements and render nothing.
We can also use all of JavaScript’s collection methods (Map, Reduce, Filter, concat, etc.) in JSX. Because they also return expressions:
const Doubler = ({value=[1, 2, 3]}) => <div> {value.map(e => e * 2)} </div>; // Use the following reactdom.render (<Doubler />, mountNode);Copy the code
Example 8: Using arrays in {}
Notice how I gave the default value for the value attribute above, because this is all just JavaScript. Notice that I’m just printing an array expression in the div. React is totally ok. It simply places each doubled value in the text node.
You can write React components using JavaScript classes
Simple function components are great for simple requirements, but sometimes we need more. React also supports the creation of components by using JavaScript classes. Here the Button component (in example 1) is written using the syntax of the class.
class Button extends React.Component {
render() {
return <button>{this.props.label}</button>; }}// Use (same syntax)
ReactDOM.render(<Button label="Save" />, mountNode);Copy the code
Example 9: Using JavaScript classes to create components
The class syntax is very simple: define an extended react.componentclass (another top-level API you’ll need to learn with React). This class defines a single instance function, render(), and makes the function return a virtual DOM object. Every time we use a class-based Button component (for example, through
This is why we can render the output using this.props. Label in JSX in the example above, because each component has a special instance property called props, which makes all values passed to the component instantiated.
Since we have an instance associated with a single use of the component, we can customize the instance as we wish. For example, we can construct it by using the regular JavaScript constructor:
class Button extends React.Component {
constructor(props) {
super(props);
this.id = Date.now();
}
render() {
return <button id={this.id}>{this.props.label}</button>; }}/ / use
ReactDOM.render(<Button label="Save" />, mountNode);Copy the code
Example 10: Custom component instances
We can also define class prototypes and use them anywhere we want, including inside the returned JSX output:
class Button extends React.Component {
clickCounter = 0;
handleClick = (a)= > {
console.log(`Clicked: The ${+ +this.clickCounter}`);
};
render() {
return (
<button id={this.id} onClick={this.handleClick}>
{this.props.label}
</button>); }}/ / use
ReactDOM.render(<Button label="Save" />, mountNode);Copy the code
Example 11: Using the properties of the class (tested by clicking the Save button)
Notice a few things in example 11 above
handleClick
Function using JavaScript newly proposedclass-field syntaxSyntax. This is still stage-2, but it is the best choice (for many reasons) for accessing the component installation instance (thanks to the arrow function). However, you need to use a compiler like Babel to decode stage-2 (or just class field syntax) for the above code to work. The jsComplete REPL has a precompile capability.
/ / error:
onClick={this.handleClick()}
/ / the correct:
onClick={this.handleClick}Copy the code
Events in 5 React: Two important differences
There are two very important differences between how we handle events in React elements and how the DOM API handles them:
- All React element attributes, including events, are usedcamelCaseName, notlowercase. For example, is
onClick
Rather thanonclick
. - Instead of a string, we pass the actual JavaScript function reference to the event handler. For example, is
onClick={handleClick}
Rather thanonClick="handleClick"
.
React wraps DOM object events in its own objects to optimize event handling performance, but we still have access to all accessible methods on the DOM object from within the event handler. React passes wrapped event objects to each calling function. For example, to prevent form submissions from being submitted by default, you can do this:
class Form extends React.Component {
handleSubmit = (event) = > {
event.preventDefault();
console.log('Form submitted');
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<button type="submit">Submit</button>
</form>); }}/ / use
ReactDOM.render(<Form />, mountNode);Copy the code
Example 12: Using wrapped objects
Each React component has a story: Part 1
The following applies only to class components (extended react.ponent). Function components have a slightly different story.
- First, we define a template to create the elements in the component.
- And then, we use React somewhere. For example, in the
render
Calls other components internally, or uses them directlyReactDOM.render
. - Then React instantiates an object and sets itpropsAnd then we can go through
this.props
Access. These are the properties we passed in step 2. - Because this is all JavaScript,
constructor
The method will be called (if defined). Here’s what we call the first one:Component lifecycle approach. - React then calculates the rendered output method (the virtual DOM node).
- Since this is the first time React is rendering an element, React will communicate with the browser (which means we’re using the DOM API) to display the element. This whole process is called mounting.
- React then calls another lifecycle function called
componentDidMount
. We can use this approach by, for example, doing something on the DOM that we now know exists in the browser. Prior to this lifecycle approach, the DOM we used was virtual. - The story of some components ends here, and others get unloaded in the browser DOM for various reasons. When the latter happens, the other lifecycle method is called,
componentWillUnmount
. - The state of any mounted element may change. The parent of the element may be rerendered. In either case, mounted elements may receive a different set of attributes. That’s the magic of React, and that’s actually what we need with React! Before that, to be honest, we don’t need React.
- The story of pricing continues, but before we do, we need to understand what I’m talking about.
React components can have private state
The following applies only to class components. Did I mention someone called a part of appearances dumb?
The status class is a special field in any React class component. React detects changes in the state of each component, but in order for React to be effective, we have to change the state fields using the React API. That’s another API we’ll learn — this.setState:
class CounterButton extends React.Component {
state = {
clickCounter: 0.currentTimestamp: new Date()}; handleClick =(a)= > {
this.setState((prevState) = > {
return { clickCounter: prevState.clickCounter + 1 };
});
};
componentDidMount() {
setInterval((a)= > {
this.setState({ currentTimestamp: new Date()})},1000);
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click</button>
<p>Clicked: {this.state.clickCounter}</p>
<p>Time: {this.state.currentTimestamp.toLocaleString()}</p>
</div>); }}/ / use
ReactDOM.render(<CounterButton />, mountNode);Copy the code
Example 13: setState API
This is probably the most important example because this is how you’ll fully understand the basics of React. After this example, there are a few little things to learn, but from then on it’s mostly you and your JavaScript skills.
Let’s take a look at example 13. Starting with the class, there are two clickCounter objects initialized with an initial value of 0 and currentTimestamp starting with new Date().
The other class is the handleClick function, where we pass the onClick event to the button element in the render method. The instance state of the component is modified by using the handleClick method of setState. Be aware of that.
Another place where we modify the state is in an internal timer, starting in the internal componentDidMount lifecycle method. It calls once a second and executes another function call this.setstate.
In the render method, we use two properties on the state with normal read syntax (no dedicated API).
Now, notice that we update status in two different ways:
- By passing in a function and returning an object. We are in
handleClick
We do this inside the function. - We do this in interval callbacks by passing in a regular object.
Both approaches are acceptable, but when you read and write states simultaneously, the first approach is preferred (which we do). In interval callbacks, we only write to the state, not read it. Always use the first function as the argument syntax when there is a problem. This is safer with race conditions because setState is actually an asynchronous method.
How should we update our status? We return an object that has the value we want to update. Notice that when we call setState, we either pass in a property from the state or not at all. This is perfectly fine because setState actually merges the existing state that you pass through it (the function argument that returns the value), so not specifying a property when calling setState means that we don’t want to change the property (but not delete it).
8. I’m going to React
The React name is derived from the reaction to a state change (although there is no reaction, it is also in a schedule). Here’s a joke. React should be named Schedule!
However, when the state of any component is updated, what we see with the naked eye is the reaction to that update and automatically reflects updates in the browser DOM (if needed).
Consider the inputs to the render function as two:
- Attributes passed through the parent element
- And an internal private state that can be updated at any time
When the input to the render function changes, the output may also change.
React keeps a history of renderings, and when it sees that one rendering is different from the previous one, it calculates the difference between them and effectively translates it into the actual DOM operations performed in the DOM.
9 React is your code
You can think of React as the proxy we use to communicate with the browser. Take the current timestamp shown above as an example. Instead of having to manually go to the browser every second to call the DOM API operations to find and update the p#timestamp element, we just change the state properties of the component, and what React does represents our communication with the browser. I believe this is the real reason why React is so popular; We just don’t like talking to Mr. Browser (and the many dialects of the DOM language it speaks), and React is volunteering to pass it on to us, free of charge!
Each React component has a story: Part 2
Now that we know the state of a component, when that state changes, let’s look at the last few concepts about the process.
- A component may need to be rerendered when its state is updated, or when its parent decides to change the properties it passes to the component.
- If the latter occurs, React calls another lifecycle method:
componentWillReceiveProps
. - If a state object or passed property changes, React has an important decision to make: should a component be updated in the DOM? That’s why it calls another important lifecycle method, right
shouldComponentUpdate
The reason why. This method is a real problem, so if you want to customize or optimize your rendering process, you must answer the question by returning true or false. - If there is no custom
shouldComponentUpdate
The React default event works fine in most cases. - First, this time another lifecycle method is called:
componentWillUpdate
. React then calculates the newly rendered output and compares it to the final rendered output. - If the rendered output is the same as the previous one, React does not process it (no need to talk to Mr. Browser).
- If there’s a difference, React communicates the difference to the browser, as we saw earlier.
- In any case, once an updater has occurred, in any way (even with the same output), React calls the last lifecycle method:
componentDidUpdate
.
The life cycle approach is the escape hatch. If you’re not doing anything special, you can create full apps without them. They are very handy to analyze what is happening in your application and further optimize the performance of React updates.
Believe it or not, with what you’ve learned (or some of it) above, you can start building some interesting React apps. If you’re hungry for more, check out my Pluralsight react.js intro course.
Thanks for reading. If you found this article helpful, please click 💚 below. Stay tuned for more articles on React.js and JavaScript.
I at Pluralsight and Lynda created an online course. My most recent posts are in Advanced React.js, Advanced Node.js, and Learning Full-stack JavaScript. I also do online and on-site training for the group, covering beginner to advanced JavaScript, Node.js, React.js, GraphQL. If you need a mentor, please come to me. If you have questions about this article or any other article I’ve written, contact me through this and ask them in # Questions.
Thanks to the many readers who examined and improved this article, ł ukasz Szewczak, Tim Broyles, Kyle Holden, Robert Axelse, Bruce Lane, Irvin Waldman and Amie Wilt.
Special thanks to “amazing” Amie, the experience was a practical Unicorn. Thank you for all your help, Anime. Thank you very much indeed.
Diggings translation project is a community for translating quality Internet technical articles from diggings English sharing articles. The content covers Android, iOS, React, front end, back end, product, design and other fields. If you want to see more high-quality translations, please continue to pay attention to The Jingjin Translation Project, official weibo, zhihu column.