“This is the 8th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021”
React
The life cycle
- Mount unmount process
- 1.1. The constructor ()
- 1.2.com ponentWillMount ()
- 1.3.com ponentDidMount ()
- 1.4.com ponentWillUnmount ()
- The update process
- 2.1. componentWillReceiveProps (nextProps)
- 2.2. ShouldComponentUpdate (nextProps nextState)
- 2.3.com ponentWillUpdate (nextProps nextState)
- 2.4.com ponentDidUpdate (prevProps prevState)
- 2.5 render ()
- React new lifecycle (personal supplement)
- 3.1. getDerivedStateFromProps(nextProps, prevState)
- 3.2. getSnapshotBeforeUpdate(prevProps, prevState)
The React lifecycle is broadly divided into three phases: mount, render, and unload
Therefore, the React lifecycle can be divided into two types: mount and unload processes and update processes. React lifecycle diagram:
1. Mount and uninstall process
1.1. The constructor ()
The React data is initialized by constructor(), which accepts two parameters: props and context. When you want to use these two parameters inside a function, you need to pass them in with super(). Note: Whenever you use constructor() you must write super(), otherwise this will point to an error.
1.2.com ponentWillMount ()
ComponentWillMount () is used less often, and more often for server-side rendering. It represents the process when the component has gone through a constructor() initialization of data, but has not yet rendered the DOM.
1.3.com ponentDidMount ()
When the component is rendered for the first time and the DOM node has been generated, an Ajax request can be called from here and the component will be rendered again after the setState data is returned
1.4.com ponentWillUnmount ()
This is where component uninstallation and data destruction are completed.
- Clear all setTimeout,setInterval in your build
- Remove removeEventListener from all builds
- Sometimes we get this warning:
Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
Copy the code
Cause: Your ajax request in the component returns setState, and when the component is destroyed, the request is not complete, so it will report warning:
componentDidMount() {
this.isMount === true
axios.post().then((res) => {
this.isMount && this.setState({ // Add condition ismount to true
aaa:res
})
})
}
componentWillUnmount() {
this.isMount === false
}
Copy the code
2. Update process
2.1. componentWillReceiveProps (nextProps)
- This is often used when props need to re-render the component after accepting changes to the parent component
- Accept a parameter, nextProps
- The component is rerendered by comparing the state of nextProps to the state of the current component
componentWillReceiveProps (nextProps) { nextProps.openNotice ! = =this.props.openNotice&&thisSetState ({openNotice: nextProps openNotice}, () = > {the console. The log (this.state.openNotice:nextProps)
// Update state to nextProps. The new state can be printed on the second parameter (callback) of setState})}Copy the code
2.2. ShouldComponentUpdate (nextProps nextState)
- Mainly used for performance optimization (partial update)
- The only way to control the life cycle of a component’s re-rendering is to setState in react and the component will enter the re-rendering process. Return false prevents the component from updating
- Rerendering of the React parent will result in rerendering of all of its children. In this case, we do not need to re-render all of the children, so we need to make decisions in the life cycle of the children
2.3.com ponentWillUpdate (nextProps nextState)
ShouldComponentUpdate returns true, the component goes to the rendering process, and goes to componentWillUpdate, where we can also get nextProps and nextState.
2.4.com ponentDidUpdate (prevProps prevState)
React will only enter componentDidmount when it is initialized for the first time, and will enter the life cycle after every re-rendering. PrevProps and prevState are the props and prevState before the update.
2.5 render ()
The Render function inserts the DOM structure generated by JSX. React generates a virtual DOM tree. At each component update, React uses its diff algorithm to compare the old and new DOM trees before and after the update, find the smallest dom nodes that differ, and re-render them.
3. React Added lifecycle (Personal supplement)
React Added life cycle
3.1. getDerivedStateFromProps(nextProps, prevState)
Instead of componentWillReceiveProps (). The old version componentWillReceiveProps () method before and after judgment two props are the same, if different then the new props to update to the corresponding state. Doing so breaks the single source of state data, making the state of the component unpredictable and, on the other hand, increasing the number of component redraws. Here’s an example:
// before
componentWillReceiveProps(nextProps) {
if(nextProps.isLogin ! = =this.props.isLogin) {
this.setState({
isLogin: nextProps.isLogin,
});
}
if (nextProps.isLogin) {
this.handleClose(); }}// after
static getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.isLogin ! == prevState.isLogin) {return {
isLogin: nextProps.isLogin,
};
}
return null;
}
componentDidUpdate(prevProps, prevState) {
if(! prevState.isLogin &&this.props.isLogin) {
this.handleClose(); }}Copy the code
The two biggest difference is: in componentWillReceiveProps, we usually do the following two things: one is based on the props to update the state, the second is to trigger some correction, such as animation or page jump.
- In the old version of the React, these two things we all need to do in the componentWillReceiveProps.
- In the new version, the update state and trigger callback are reassigned to getDerivedStateFromProps and componentDidUpdate, making the overall update logic of the component clearer. Also, getDerivedStateFromProps disallows the component from accessing this. Props, forcing the developer to compare the values of nextProps and prevState. To make sure that when developers use the getDerivedStateFromProps lifecycle function, they are updating the component’s state based on the current props, rather than doing something else that makes the component’s state more unpredictable.
3.2. getSnapshotBeforeUpdate(prevProps, prevState)
ComponentWillUpdate instead. A common use case for componentWillUpdate is to read the current state of a DOM element and process it in componentDidUpdate before the component is updated. The difference between the two is:
- When asynchronous render mode is enabled in React, the DOM element states read in render are not always the same as those read in commit. This makes it unsafe to use the DOM element states read in componentWillUpdate in componentDidUpdate because the values are likely to be invalid.
- GetSnapshotBeforeUpdate is called before final render, which means that the DOM element states read in getSnapshotBeforeUpdate are guaranteed to be the same as in componentDidUpdate. Any values returned by this life cycle are passed as arguments to componentDidUpdate ().
JSX profile
What is JSX??
Looking back at the code above,
Hello World!
Isn’t that weird? How can THERE be HTML tags in JS? !
Yes, JS can write HTML tags, this form, is JSX.
JSX is neither a string nor HTML. It is a syntax for writing HTML tags in JS.
You can also assign it this way. const element =
Hello World!
In JSX, you can also declare variables or introduce expressions with {}. You can put any JS expression in {}.
Such as
Hello, Zhang {1 + 2}
Or we could say const name = ‘zhang SAN’
hello {name}
Note: the JSX class attribute should be written as className.
After reading this, YOU must still be confused about JSX.
But don’t worry, there will be a lot of JSX in the future, and if you use more, you will definitely love it!
component
Component, similar to JS functions. However, the function name of the component should be capitalized. (Lowercase is function, uppercase is component)
A component is a separate piece of code. Call render directly when needed.
Component, which is written in two standard ways:
First, of functional form, for example:
function Welcome() { return ( <h1>Hello world! </h1> ) } ReactDOM.render( <Welcome />, document.getElementById('root') )Copy the code
Second, of the class form, e.g.
class Welcome extends React.Component { render() { return ( <h1>Hello World! </h1> ) } } ReactDOM.render( <Welcome />, document.getElementById('root') )Copy the code
So these two ways of writing it are equivalent.
So these two ways of writing it are equivalent.
Two examples, two standard formats. That is, it doesn’t matter what form you use or what content you render.
Composition versus inheritance
Official documentation: clever use of combination, careful use of inheritance
Composition is very easy to use in the actual coding process, and we have used it many times in the process of learning.
For example:
function App1() { return ( <h1>Hello, React! </h1>)} function App2() {return (<h1> react! } function App3() {return (<div> <App1 /> <h3> </h3> <App2 /> </div> ) } ReactDOM.render( <App3 />, document.getElementById('root') )Copy the code
/ / the case was put through App3 component App1 and App2 together, through the render renders. Output result:
Hello, React! Hello react!Copy the code
The CSS class name
Use className instead of className. React JSX uses className instead of className.
`Warning: Invalid DOM property `class`. Did you mean `className`?
Copy the code
<input className="input" />
Copy the code
Conditions apply colours to a drawing
import React, {Component} from 'react'
class Condition extends Component {
constructor(props) {
super(props)
this.state = {
show: false.list: [{id: 1.age: 11},
{id: 2.age: 22},
{id: 3.age: 33}}},]render() {
// If else render
if(this.state.show) {
return <p>hello</p>
}else {
return <p>byebye</p>
}
// A ternary expression
// return (this.state.show ? <p>hello</p> : <p>byebye</p>)
/ / and operation &&, or operational | |
// return this.state.show && <p>hello</p>
// return this.state.show || <p>byebye</p>}}export default Condition
Copy the code
suspense
Suspense usually works with asynchronous components to add wait animations or other actions when asynchronous components are not loading
import React,{ Component, Suspense } from 'react';
const AsyncComp = React.lazy(() = > import('./FormInput'))
class SuspenseDemo extends Component {
render() {
// fallback represents the display effect before the asynchronous operation
return <Suspense fallback={<div>Loading...</div>}> {/* Here is the component introduced asynchronously */}<AsyncComp/>
</Suspense>}}export default SuspenseDemo;
Copy the code
Render loop
For map rendering, the key is the same as vUE, and index or random is generally not set
// Loop render
return (
<ul>
{this.state.list.map(item =>
{
return <li key={item.id}>{item.age}</li>})}</ul>
)
Copy the code
State of the state
- use
this.state
Define the state to usethis.setState({xxx: xxx})
Mode To modify the status state
The data cannot be used directlythis.state.xxx = xxx
Form to change the state becausereact
theimmutable
It’s conceptually determined. It specifiesstate
The data cannot be changed directly in thesetState
Mode modification, must bestate
Make a copy of your data for modification
import React, { Component } from 'react'
class SetStateDemo extends Component{
constructor(props) {
super(props)
this.state = {
count: 0.list: [{id: 1.age: 1},
{id: 2.age: 2}
]
}
}
addCount = () = > {
// It is recommended to use this method to copy the original data and modify it
const newList = this.state.list.slice()
newList.push(3)
this.setState({
// if this.state.count++ is used, a warning will be issued because this line directly changes the value of the original count:
// Do not mutate state directly. Use setState()
// count: this.state.count++
count: this.state.count + 1.list: newList
})
console.log(this.state.count) // This is asynchronous
}
render() {
return (
<div>
<p>{this.state.count}</p>
<button onClick={this.addCount}>cumulative</button>
</div>)}}export default SetStateDemo;
Copy the code
The event
- Event to use
on
+Capital hump
For exampleonClink={this.xxx}
Is the same asThe vue @ click = "XXX"
- event-related
this
To:- The first way:
- use
ES5
Way to define events,this
Will default toundefined
, in order to usebind
To bindthis
Point, or an error will be reportedCannot read property 'setState' of undefined
- The event
bind(this)
Written in the bestconstructor
, this will only be executed oncebind
And cache the results, if written on the label, click once to executebind
, and when used in more than one place, more than one placebind
, so write inconstructor
Is a performance optimization
- use
- The second way to write it is to use
ES6
Arrow function,this
Will default to the current instance, do not need to worry aboutthis
Point to, but may need tobabel
To translate
- The first way:
import React, { Component } from 'react'
class Event extends Component {
constructor(props) {
super(props)
this.state = {
name: 'flower',}// The first way is to bind this to the event
this.handleClick = this.handleClick.bind(this)}render() {
// When clicked multiple times, bind will be triggered multiple times
// Bind only once from constructor, saving cached results as a performance optimization
// return <p onClick={this.handleClick.bind(this)}>{this.state.name}</p>
// Bind events using the onXxxx notation
return (
<div>{/* the first way */}<p onClick={this.handleClick}>{this.state.name}</p>{/* Second way */}<p onClick={this.handleClick2}>{this.state.name}</p>
</div>)}// The first definition method
handleClick() {
// Modify data with setState
this.setState({
name: 'small'})}// The second way to define a method is to use the arrow function so that this points to the current instance
handleClick2 = (event) = > {
console.log(event);
// Modify data with setState
this.setState({
name: 'small'}}})export default Event
Copy the code
- Nature of the event
- in
react
In the useevent
Gets the current event, but sees that the print isSyntheticBaseEvent
, this isreact
Synthetic events are not nativeMouse Event
It simulates all the capabilities of DOM events, including bubbling, blocking events, and so on - Can be achieved by
event.nativeEvent
Get native events - All the events in the
react16
Before, they were all mounted todocument
On; inreact17
After, it will be mounted toroot
On the root element, this favors multipleReact
Version coexistence, such as micro front-end; Can be achieved byevent.navtiveEvent.currentTarget
To get the mount element - This and
dom
The events are different, andvue
The events were different,vue
The event is nativeMouse Event
And will be mounted to the current element
- in
render() {
return (
<div>{/* react event properties */}<a href="http://www.baidu111.com" onClick={this.handleClick3}>Skip links</a>
</div>)}Copy the code
// React
handleClick3 = (event) = > {
console.log('handleClick3');
// SyntheticBaseEvent is a synthetic Event handled by React itself, not a native Mouse Event
// This is different from vue, where events are native and are mounted to the current element via $event
console.log(event)
event.preventDefault() // Block native operations, such as a TAB jump, right chain menu, etc
event.stopPropagation() // Prevent bubbling
// Get the native event MouseEvent
console.log('event nativeEvent:', event.nativeEvent);
// Native event object, jump link
console.log('nativeEvent target:', event.nativeEvent.target)
// The object that was mounted to document before React16 and root after react17
console.log('nativeEvent currentTarget:', event.nativeEvent.currentTarget )
}
Copy the code
image.png
- Parameter passing to the event
- use
bind
The custom parameter is passed from the second
<p onClick={this.handleClick4.bind(this, 'aa', 'bb')} >Event reporter I</p>
Copy the code
// Event is added to the last parameter by default
handleClick4(a, b, event) {
console.log('parameters:, a, b, event); // Parameter: aa bb SyntheticBaseEvent
}
Copy the code
- Using the arrow function,
event
Need to be defined in the returned function
<p onClick={this.handleClick5('aa')} >Event parameter 2 was transmitted</p>
Copy the code
// We need to return a function with event as an argument
handleClick5 = (a) = > {
return (event) = > {
console.log('a', a); // aa
console.log('e', event); // SyntheticBaseEvent}}Copy the code
- When binding, use the arrow function that will
event
Parameter passing, recommended to use this method, the writing method is convenient and concise
<p onClick={(e)= >This.handleclick6 ('aa', e)}> EventPass parameter 3</p>
Copy the code
// There is no need to return a function
handleClick6 = (a, event) = > {
console.log(a);
console.log(event)
}
Copy the code
The controlled components
A controlled component, as its name suggests, means that the state of the component is controlled by React. Vue uses the V-Model to bind forms in both directions. React does not provide a similar API, so you need to implement it:
- for
input
,textarea
,select
And so on are controlledvalue
Value to control the form content, throughonChange
To listen for form input - for
radio
,checkbox
And so on through controlchecked
Value to control the form content, throughonChange
To listen for form input
import React, { Component } from 'react';
class FormInput extends Component {
constructor(props) {
super(props)
this.state = {
name: 'flower'.info: 'xxxx'.city: 'shenzhen'.flag: true.gender: 'female'.like: ['basketball']}}render() {
let { name, info, city, gender, like } = this.state
// Form controlled components
return <div>
<p>{name}</p>
<label htmlFor="inputName">Name:</label>
<input type="text" id="inputName" value={name} onChange={this.inputChange}/>
<hr/>
<p>Personal Information:<span>{info}</span></p>
<textarea value={info} onChange={this.textareaChange}></textarea>
<hr/>
<p>City:<span>{city}</span></p>
<select value={city} onChange={this.selectChange}>
<option value="beijing">Beijing</option>
<option value="shenzhen">shenzhen</option>
<option value="shangehai">Shanghai</option>
</select>
<hr/>
<p>Gender:<span>{gender}</span></p>
男 <input type="radio" name="gender" value="male" checked={gender= = ='male'} onChange={this.radioChange}/>
女 <input type="radio" name="gender" value="female" checked={gender= = ='female'} onChange={this.radioChange}/>
<hr/>
<p>Likes: {like.map(item => {return<span>{item}</span>
})}</p>
<input type="checkbox" value="basketball" checked={like.includes('basketball')} onChange={this.checkboxChange}/>basketball<input type="checkbox" value="football" checked={like.includes('football')} onChange={this.checkboxChange}/>football</div>
}
inputChange = (e) = > {
this.setState({
name: e.target.value
})
}
textareaChange = (e) = > {
this.setState({
info: e.target.value
})
}
selectChange = (e) = > {
this.setState({
city: e.target.value
})
}
radioChange = (e) = > {
this.setState({
gender: e.target.value
})
}
checkboxChange = (e) = > {
const val = e.target.value
let newLike = this.state.like.slice();
if(this.state.like.indexOf(val) ! = = -1) {
let index = this.state.like.indexOf(val)
newLike.splice(index, 1)}else {
newLike.push(val)
}
this.setState({
like: newLike
})
}
}
export default FormInput
Copy the code
Communication between parent and child components
Similar to VUE, but the parent component methods and properties are passed through properties (unlike Vue, where events are passed through V-ON /@), the child component does not emit the parent component methods, but this. Props. ParentMethod
/ / the parent component
render() {
return (
<TodoItem
content={item}
index={index}
deleteItem={this.handleDelete.bind(this)}
/>
)
}
handleDelete=(index) = >{
// Immutable is a concept that does not allow you to modify data directly on state, otherwise later performance tuning may be problematic
let list = [...this.state.list] // Make a copy of it and make changes on it
list.splice(index,1)
this.setState({
list: list
})
}
Copy the code
/ / child component
import React, { Component } from 'react'
class TodoItem extends Component {
constructor(props) {
super(props);
// Point this to the current React component. Specify this in the constructor to optimize performance
this.handleClick = this.handleClick.bind(this)}render() {
return (
// Before the optimization, we can write:
//<div onClick={this.handleClick.bind(this)}></div>
<div onClick={this.handleClick}></div>)}handleClick() {
// Trigger the parent component method
this.props.deleteItem(this.props.index)
}
}
Copy the code
State of ascension
Often, multiple components need to reflect the same changing data, and we recommend promoting the shared state to the nearest common parent. This is called state elevation.
Personally, I feel that the cases given in the official documents are a little difficult to look at, so I wrote a length conversion case as follows:
Let dataTitle = {m: 'input m: ', cm: 'Input cm: LengthData extends React.Component {render() {let title = this.props this.props.input let onChange = this.props.onChange let data = this.props.data return ( <fieldset> <legend>{title}</legend> <input type="text" value={data} onChange={onChange} /> </fieldset>)}} // Write a component class that implements the input box {constructor(props) {super(props) // state = {type: '', input: '' } } checkedInput(input) { // console.log(typeof(input)) if (Number.isNaN(input) || parseFloat(input) < 0) { alert (' Incorrect input data, re-enter! ') this.setState({ type: '', input: '' }) } return input } convertCM(input) { return input * 100 } convertM(input) { return input / 100 } handleChange=(type, e) => { if (type === 'meter') { this.setState({ type: 'meter', input: e.target.value }) }else if (type === 'centimeter') { this.setState({ type: 'centimeter', input: E.targe.value})}} render() {// Meter rectification type data these are variables that are set up for interaction let input = this.state.input let type = this.state.type let meter = type === 'centimeter' ? this.convertM(this.checkedInput(input)) : input let centimeter = type === 'meter' ? this.convertCM(this.checkedInput(input)) : Input return (<div> <h3> </h3> <LengthData title={datatitle. m} data={meter} onChange={(e)=> {this.handleChange('meter' ,e)}} /> <LengthData title={dataTitle.cm} data={centimeter} onChange={(e)=> {this.handleChange('centimeter' ,e)}} /> </div> ) } } ReactDOM.render( <Length />, document.getElementById('root') )Copy the code
** Step 1: ** Write the component that implements the input box (this step is not obvious in the code case)
** Step 2: ** Extract input box components (easy to write multiple input boxes)
** Step 3: ** State promotion (remove the state from the child component and put the state in the parent component)
** Step 4: ** State interaction (core code, also the most difficult code to understand)
** Step 5: ** Debug bugs (debug input and output results, such as input does not meet requirements, give error messages, and then empty the input field to prevent interaction)
react-redux
1. What is redux
Official explanation: Redux is a container of predictable state for JS applications. Can be understood as a global data state management tool (state manager), used to do component communication, etc.
2、为什么使用redux
When redux is not used, passing values between sibling components is cumbersome and the code is complex and redundant. Using Redux to define a global single data Store, you can customize what data is stored in the Store, and the entire data structure is also clear.
3, the state
State in the front end is data, it’s an object. State in redux cannot be changed directly, only through action, which is equivalent to defining setter methods in a singleton.
4, the action
Redux describes each change as an action, and to change the contents of state, you need to send the action. An action is a simple object that describes what has changed in state.
const INCREMENT = 'INCREMENT'
const incrementAction = {"type": INCREMENT, "count": 2}
Copy the code
This is an action, which is an object, based on the type of the action.
5, reducer
The data state indicates that the action is there so it’s implemented. Reducer is a reducer that controls state based on actions.
const calculate = (state: ReduxState = initData, action: Action ) => {
switch (action.type) {
case INCREMENT:
return {num: state.num + action.count}
case REDUCE:
return {num: state.num - action.count}
default:
return state
}
}
export {calculate}
Copy the code
A new state is returned after the reducer operation, such as adding or subtracting state.num based on the action type.
6, store
A store is where data is stored for the entire project, and there can only be one. Create a store and reducer everything into it.
import { createStore, combineReducers } from "redux";
import { calculate } from "./calculate";
You can create multiple reducers together here
const rootReducers = combineReducers({calculate})
// Manage a store globally
export const store = createStore(rootReducers)
Copy the code
7, dispatch
Store.dispatch () is the only way a component can issue an action.
store.dispatch(incrementAction);
Copy the code
By calling incrementAction from the store, the store data is modified directly.
8. Use of Redux
Article: www.jianshu.com/p/794f5aabb…
Video: www.bilibili.com/video/BV1d4…