I have been learning and using react for more than a year. I recently want to sort out the basic knowledge of react, lay a solid foundation, and make progress~
React-router, redux, and redux-saga will be output slowly in the future. I hope all the readers will continue to pay attention~~If you can give me a thumbs up and encourage me, it will be even more praise~
A reminder:
After reading it, hurry up and strike while the iron is hot, redux, react-redux, redux-saga
Quick look at the basics of react
1. What is JSX?
An example of JSX syntax as shown below
const element = <h1>Hello, world!</h1>;
This syntax form is neither HTML nor string, but is called JSX. It is a syntax used in React to describe UI and styles. JSX will eventually be compiled into a legal JS statement call (the compiler uses JS syntax to parse when encountering {, and uses HTML rules to parse when encountering <)
2. Embed expressions
In JSX, you can use curly braces {} to embed any JavaScript legal expression, such as: 2 + 2, formatName(user) is both legal. Examples such as:
const user = { firstName: 'Zhang', lastName : 'Busong' }; const elem = ( <h1>Hello, {formatName(user)}</h1> ); /* The () here is actually optional, but React recommends adding(), so that it will be regarded as an expression without causing it. Problem of inserting semicolons automatically */ ( element, ('app') )
3. JSX is also an expression
JSX itself is also an expression, so it can be used like other expressions to assign values to a variable, as a function parameter, as a function return value, etc. like:
function getGreeting(user) { if (user) { return <h1>Hello, {formatName(user)}</h1> } return <h1>Hello, Guest!</h1>; }
Notice:
1. In JSX, do not use quotes when declaring properties. If quotes are used when declaring properties, they will be parsed as strings and will not be parsed as an expression, such as:
<div firstName="{}" lastName={}></div>
After parsing, you can get:
<div firstName="{}" lastName="Lau"></div>
Therefore, when we need to use a string literal, we can use quotes, but if we want to parse as an expression, we should not use quotes.
2. In JSX, some attribute names need to be processed specifically. If class should be replaced with className, tabIndex should be replaced with tabIndex. This is because JSX is essentially closer to JavaScript, and class is a reserved word in JavaScript. At the same time, a property should be named using camelCase, rather than using HTML attribute naming method
3. JSX itself has been anti-injected. For HTML code that is not explicitly written, it will not be parsed into HTML DOM. ReactDOM will treat them as strings and convert them into strings before rendering is completed, so it can prevent XSS attacks.
4. If the JSX tag is closed, then the ending needs to be used. In addition, the JSX tags can be nested with each other, which is the same as in HTML.
4. JSX essence
JSX is compiled through babel, and babel actually compiles JSX to the () call. The following JSX code:
const element = ( <h1 className="greeting"> Hello, world! </h1> );
It is equivalent to the following statement:
const elem = ( 'h1', {className: 'greeting'}, 'Hello, world!' );
The () method will first perform some checks to avoid bugs, and then return an object similar to the following example:
const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world' } }
Such an object is called a React element, representing everything that is presented on the screen. React builds the DOM by reading these objects and keeps the data and UI synchronized
5. Element Rendering
Elements are the smallest units that make up a React application. Elements describe what you want to see on the screen, such as:
const element = <h1>Hello, world</h1>;
Unlike DOM elements, React elements are pure objects and are low-cost to create. And React will optimize and update only necessary changes to the DOM. In addition, the concepts of elements and components are different, and components are composed of elements.
6. Render elements into DOM
In React, use the() method to render React elements into a DOM. like:
( element, ('root') )
React elements are immutable, so once an element is created, we cannot change its content or attributes. An element is like a frame in an animation, which represents the appearance of the UI at a certain point in time. If you have to use elements to form a variable UI interface, you need to use setInterval, such as:
function tick() { const element = ( <div>Now is {new Date().toLocaleTimeString()}</div> ); ( element, ('root') ); } setInterval(tick, 1000);
In actual development, most React applications will only call() once, so a better way is to use stateful components
7. Components and Props
Components can divide the UI into separate, reusable parts so that we only need to focus on building each individual component.
Conceptually, components are like functions: accepting arbitrary inputs (called properties, Props), returning React elements. There are two ways to define components in React: function definition and class definition
1. Function definition components
This method is the easiest way to define components, just like writing a JS function, like:
function Welcome (props) { return <h1>Hello, {}</h1>;; }
2. Class definition components
You can also use the class in ES6 to define a component, as shown below:
class Welcome extends { render () { return <h1>Hello, {}<h1>; } }
This method is more flexible than function definition
3. Component rendering
Previously, the React element we encountered just rendered a DOM tag, such as:
const element = <div />
However, React elements can also be user-defined components such as:
const element = <Welcome name="Tom" />
A property name="Tom" is declared in the Welcome component, and this property will be passed to the component in the following way:
function Welcome (props) { return <h1>Hello, {}</h1>; }
At this point, for the following code:
( <Welcome name="Zhang Busy" />, ('root') )
In the end, it will be presented in the way of <h1>Hello, Zhang Bushuang</h1>. In this process, the following things happened:
- Called () rich on the <Welcome name="Zhang Bushuang" /> element
- React calls the Welcome component with { name: 'Zhang Bushuang' } as a props argument
- Welcome completes rendering, returns the <h1>Hello, Zhang Bushuang</h1> element
- ReactDOM calculates the minimum update cost and then updates the DOM
4. Combination components
Components can be combined. That is, other components can be referenced inside the component, such as:
function Welcome (props) { return <h1>Hello, {}</h1>; } function App () { return ( <div> <Welcome name="Tom" /> <Welcome name="Jack" /> <Welcome name="Mike" /> </div> ) } ( <App />, ('root') )
Note: In React, components must return a single root element, which is why the <div> tag needs to be wrapped in App components. As in the following way, it is wrong (because it has 3 root elements):
function App () { return ( <Welcome name="Tom" /> <Welcome name="Jack" /> <Welcome name="Mike" /> ) }
5. Properties are read-only
Consider the following situation:
function sum (a, b) { return a + b; }
This kind of function is called a pure function: it does not change its input value and always returns the same result for the same input.
Opposite it is a non-pure function, such as:
function withdraw (account, amount) { -= amount; }
A non-pure function changes the input parameters within the function. In React, we should not modify its own properties (props) whether it is declared through function or class. Although React is quite flexible, it also has a strict rule: All React components must use their props like pure functions
8. State and life cycle
There are some additional benefits of using class definition components, such as having the local state feature.
The following is a class definition component
class Clock extends { render () { return ( <div> <h1>Hello, world!</h1> <h2>Now is {()}</h2> </div> ); } }
What needs to be noted are:
The class name is the component name (whether it is a function definition component or a class definition component, the first letter of the component name must be capitalized and inherited from)
Use the render() method to return the content to be rendered
1. Add state to the class
The state belongs to a component itself. We can initialize the state in the constructor of the class, such as:
constructor (props) { super(props) = { date: new Date() } }
In this way, we can use it in the render() function to refer to a state
2. Life cycle
There are often many components in applications. After components are destroyed, it is important to recycle and release the resources they occupy.
In the example of clock application, we need to set a timer when the DOM is rendered for the first time, and we need to clear this timer after the corresponding DOM is destroyed. So, in this case, React provides us with a hook function for life cycle, which is convenient for us to use. In React, life cycles are divided into:
1) Mount has been inserted into the real DOM
2) Update is re-rendering
3) Unmount has been removed from the real DOM
And correspondingly, the life cycle hook function is:
- componentWillMount
- componentDidMount
- componentWillUpdate(newProps, nextState)
- componentDidUpdate(prevProps, prevState)
- componentWillUnmount()
In addition, there are two special state processing functions:
- componentWillReceiveProps(nextProps) is mobilized when a loaded component receives a new parameter
- ShouldComponentUpdate(nextProps, nextState) Called when the component determines whether to re-render
Therefore, based on the life cycle hook function, we can implement a clock application as follows:
class Clock extends { constructor (props) { super(props); = { date: new Date() } } tick () { ({ date: new Date() }); } componentDidMount () { = setInterval(() => { () }, 1000); } componentWillUnmount () { clearInterval(); } render () { return ( <div>Now is {()}</div> ); } }
What should be noted is:
1) State that cannot be used in render() should not be declared in state
2) You cannot directly use = xxx to change the value of a state, you should use (). like:
setName () { ({ name: 'Zhang Busy' }) }
() will automatically overwrite the corresponding properties in it and trigger render() to re-render.
3) Status update may be asynchronous
React can combine multiple setState() calls into one call to improve performance. And since sums may be updated asynchronously, they should not be relied on their values to calculate the next state. In this case, you can pass a function to setState, such as:
((prevState, props) => ({ counter: + }));
9. Event handling
Events of React elements are similar to those of DOM elements, but there are some differences, such as:
1) React events are named (onClick) instead of all lowercase form (onclick)
2) Using JSX, the handle of the event is passed, not a string
HTML like the following:
<button onclick="increment()">ADD</button>
Using React describes it as follows:
<button onClick={increment}>ADD</button>
Another difference is that in native DOM, we can block the default behavior by returning false, but this does not work in React. In React, it is necessary to explicitly use preventDefault() to block the default behavior. like:
function ActionLink () { function handleClick (e) { (); alert('Hello, world!'); } return ( <a href="#" rel="external nofollow" onClick={handleClick}>Click Me</a> ); }
Here, the event in the event callback function is specially processed by React (following the W3C standard), so we can use it with confidence without worrying about cross-browser compatibility issues.
Note: When using event callback functions, we need to pay special attention to this pointing problem, because in React, except for the constructor and life cycle hook functions, this will be automatically bound to this pointing as the current component, otherwise we will not automatically bind this pointing as the current component. Therefore, we need to pay attention to this binding problem.
Generally speaking, if you use event callbacks in a component declared in a class, we need to bind this pointer of the callback method in the component's constructor, such as:
class Counter extends { constructor (props) { super(props); = { counter: 0 } // Here binding pointer = (this); } increment () { ({ counter: + 1 }); } render () { return ( <div> The counter now is: {} <button onClick={}>+1</button> </div> ); } }
Of course, we have another way to use arrow function binding pointers, which is to use experimental attribute initialization syntax, such as:
class Counter extends { increment: () => { ({ counter: + 1 }); } // ... }
3) Pass parameters like event handler
We can pass additional parameters to the event handler in two ways:
<button onClick={(e) => (id, e)}>Delete Row</button> <button onClick={(this, id)}>Delete Row</button>
It should be noted that when using arrow functions, the parameter e must be passed explicitly, while when using bind, there is no need to be explicitly passed (the parameter e will be passed as the last parameter to the event handler)
10. Conditional Rendering
In React, we can create different components to encapsulate the functionality we need. We can also render only part of the content in the component according to the state of the component, and conditional rendering is prepared for this. In React, we can write conditional rendering statements like we write conditional statements in JavaScript, such as:
function Greet(props) { const isLogined = ; if (isLogined) { return <div>Hello !</div>; } return <div>Please sign in</div>; } ( <Greet isLogined={true} />, ('root') );
This will render:
<div>Hello !</div>
1. Use variables to store elements
We can also use variables to store elements, such as:
function LogBtn(props) { var button; const isLogined = ; if (isLogined) { button = <button>quit</button> } else { button = <button>Log in</button> } return <div>You can {button}</div>; } ( <LogBtn isLogined={false} />, ('root') );
2. Use the && operator for rendering
Due to the nature of JavaScript syntax treats the && operator, we can also use the && operator to complete conditional rendering, such as:
function LogBtn(props) { var button; const isLogined = ; return ( <div>Hello {!isLogined && ( <button>Please log in</button> )} </div> ) }
When false, it will render:
<div>Hello <button>Please log in</button></div>
3. Use the trinocular operator for rendering
We may have discovered that JSX can actually be used flexibly like an expression, so we can naturally use trigonometric operators for rendering, such as:
function LogBtn (props) { const isLogined = ; return ( <div>You can <button>{isLogined ? 'quit' : 'Login'}</button> </div> ) }
4. Prevent the rendering of the entire component
Sometimes, we hope that the entire component will not be rendered, not just locally, so in this case, we can return a null in the render() function to achieve the effect we want, such as:
function LogBtn (props) { const isLogined = ; const isShow = ; if (isShow) { return ( <div>You can <button>{isLogined ? 'quit' : 'Login'}</button> </div> ) } return null; }
Note: Returning null in the component will not affect the trigger of the component's life cycle. For example, componentWillUpdate and componentDidUpdate will still be called.
11. List rendering and keys
In JavaScript, we can use the map() function to operate on an array list, such as:
const numbers = [1, 2, 3, 4, 5]; const doubled = (number => number*2); (doubled); // Get [2, 4, 6, 8, 10]
Similarly, in React, we can also use map() to render lists, such as:
const numbers = [1, 2, 3, 4, 5]; const listItems = (number => { return ( <li>{number}</li> ) }); ( <ul>{listItems}</ul>, ('root') )
This will get:
<ul><li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul>
Of course, we can also perform better packaging, such as:
function NumberList (props) { const numbers = ; const listItems = (number => { return ( <li>{number}</li> ) }); return <ul>{listItems}</ul> }
When we run the above code, we will find a console prompt: Each child in an array or iterator should have a unique "key" prop. Therefore, we need to assign a key to each item in the list to solve this problem. Generally speaking, we can use the following ways to provide the key:
Use the data item's own ID, such as <li key={}>
Use index index (index), such as:
const listItems = ((number, index) => { <li key={index}>{number}</li> });
However, React does not recommend using index subscripts in lists that need to be reordered, as it will become very slow.
Note: Key is only needed to use when distinguishing between compatriots of an item. Key does not need to be globally unique, it only needs to be unique when distinguishing between each other within an array. The function of key is to give React a prompt, not passed to the component. If we need the same value in the component, we can pass it in a different name, such as:
const content = (post => ( <Post key={} id={} title={} /> ));
12. Form
The DOM element in form is different from other React because form elements are born to save some internal state. In React, forms and forms in HTML are slightly different
1. Controlled components
In HTML, form elements such as <input>, <textarea>, and <select> will maintain their own state and update them according to user input. However, in React, variable states are usually stored in the component and can only be updated using the setState() method, such as:
class NameForm extends { constructor (props) { super(props); = { value: '' } = (this); = (this); } handleChange (event) { ({ value: }); } handleSubmit (event) { alert('Your name is '+); (); } render () { return ( <form onSubmit={}> Name: <input type="text" value={} onChange={} /> <input type="submit" value="Submit" /> </form> ) } }
Unlike HTML, textarea in React does not need to be written in the form of <textarea></textarea>, but in the form of <textarea value="" ... />. For select tags in HTML, the usual practice is:
<select> <option value="A">A</option> <option value="B" selected>B</option> <option value="C">C</option> </select>
However, in React, you do not need to add selected options at the option that needs to be selected, but only need to pass in a value, and the corresponding options will be automatically selected according to the value, such as:
<select value="C"> <option value="A">A</option> <option value="B">B</option> <option value="C">C</option> </select>
Then as in the above example, the option where C is located will be selected.
2. Solutions for multiple inputs
Usually a form has multiple inputs, and it will be very cumbersome if we add processing events for each input. A good solution is to use name and then choose what to do according to it. like:
class Form extends { constructor (props) { super(props); = { name: '', gender: 'male', attend: false, profile: '' }; = (this); = (this); } handleInputChange (event) { const target = ; const value = ==='checkbox' ? : ; const name = ; ({ [name]: value }); } handleSubmit (event) { ({ profile: `Name:${},${},${ ? 'join' : 'Not to participate'}Activity` }); (); } render () { return ( <form> <p>Name:<input name="name" value={} onChange={} /></p> <p>gender: <select name="gender" value={} onChange={}> <option value="male">male</option> <option value="female">female</option> </select> </p> <p>Whether to participate:<input name="attend" type="checkbox" onChange={} checked={} /></p> <input type="submit" value="Submit" onClick={} /> <p>Your registration information:{}</p> </form> ) } }
3. Uncontrolled components
In most cases, it is preferred to implement forms using controlled components, where form data is handed over to the React component. If you want the form data to be processed by the DOM (that is, the data is not saved in the state of React, but in the DOM), you can use uncontrolled components and use uncontrolled components. You can use event handlers for each state update without writing an event handler, and you can use ref to achieve it, such as:
class NameForm extends { constrcutor(props) { super(props) } handleSubmit(event) { ('A name was submitted: ', ) () } render() { return ( <form onSubmit={}> <label> Name: <input type="text" ref={input => = input} /> </label> <input type="submit" value="submit" /> </form> ) } }
For uncontrolled components, if you want to specify a default value, you can use defaultValue, such as:
<input type="text" defaultValue="Hello" ref={input => = input} />
Accordingly, type="checkbox" and type="radio", defaultChecked is used
13. Status improvement
When several components need to share state data, state enhancement technology can be used. The core idea is to extract the data to the nearest common parent component, the parent component manages the state (state), and then pass it to the child component through attributes (props). If a component that implements a currency conversion, it can be as follows:
1. Define the conversion function first
function USD2RMB (amount) { return amount * 6.7925; } function RMB2USD (amount) { return amount * 0.1472; } function convert (amount, typeFn) { return typeFn(amount); }
2. Define components
We hope that when entering on the RMB input form, the values on the USD input form will also be updated synchronously. In this case, it is difficult to achieve if the RMB component manages its own state by itself. Therefore, we need to improve this state from the parent component for management. as follows:
class CurrencyInput extends { constructor (props) { super(props) = (this) } handleChange (event) { () } render () { const value = const type = return ( <p>{type}: <input type="text" value={value} onChange={} /></p> ); } }
Finally, a common parent component is defined as follows:
class CurrencyConvert extends Component { constructor (props) { super(props); = { type: 'RMB', amount: 0 } = (this); = (this); } handleRMBChange (amount) { ({ type: 'RMB', amount }); } handleUSDChange (amount) { ({ type: 'USD', amount }); } render () { const type = ; const amount = ; const RMB = type==='RMB' ? amount : convert(amount, USB2RMB); const USD = type==='USD' ? amount : convert(amount, RMB2USB); return ( <div> <p>Please Input:</p> <CurrencyInput type="RMB" value={RMB} onInputChange={} /> <CurrencyInput type="USD" value={USD} onInputChange={} /> </div> ); } }
14. Combination vs inheritance
React advocates more about using combinations than inheritance. For some usage scenarios, React gives the following suggestions:
1. Including relationships
When the parent component does not know what the child component is possible, it can be used, such as:
function Article (props) { return ( <section> <aside>Sidebar</aside> <article>{}</article> </section> ); } function App () { return ( <Article>This is an article</Article> ); }
This renders it to get:
<section> <aside>Sidebar</aside> <article>This is an article</article> </section>
We can also customize the name because JSX will actually be converted into a legal JS expression, so there can also be:
function Article (props) { return ( <section> <aside>{}</aside> <article>{}</article> </section> ); } function App () { return ( <Article aside={ <h1>This is a sidebar</h1> }>This is an article</Article> ); }
This renders it to get:
<section> <aside><h1>This is a sidebar</h1></aside> <article>This is an article</article> </section>
2. When to use inheritance?
On Facebook's website, thousands of components are used, but practice has proven that there is no situation that requires inheritance to be resolved.
Attributes and combinations provide us with a clear and secure way to customize the style and behavior of components. Components can accept any element, including: basic data types, React elements, and functions.
If you want to reuse UI-independent functions between components, you should extract them into a separate JavaScript module, so that functions, objects, and classes can be imported without extending the components
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.