It took about 12 days to have a preliminary understanding of React. Compared to Vue, it felt more complicated, especially redux, which was quite confused when learning….. B: Maybe I’m just too lazy. Remember to keep to the official documentation. And don’t watch any old videos, especially those from before version 16. Hooks weren’t used then.

I refer to teacher Coderwhy’s video, which feels very good as well as details of the source code and so on. Just his absorption capacity is a bit weak, still need to consolidate more!

Learned more than half a year of the front end, this is readily written notes, a lot of places are certainly insufficient, I hope the big guys more correct

If this article helps you, it makes sense hahaha

1, Hello React

UI = render(state)

Image loading optimization: the back end of the image to pass the size, although the style can be changed, but large image consumption performance

Imperative programming: The computer is given step-by-step instructions to perform each operation

Declarative programming:

1.1 JSX grammar

Note: With JSX code, text/ Babel must be added to script

The render function can only have one root node, as JSX syntax does, enclosing parentheses

Single tags must end with /> and/cannot be omitted

Comments must be written in {/

I’m a note

/}

Attributes that cannot be displayed in {} : null, undefined, and Boolean are not displayed

If you want to display null, you can use toString (), or you can add an empty string after it

You can’t put an object inside {}

You can put operator expressions into string concatenation addition, subtraction, multiplication and division

You can put a ternary expression

You can put functional expressions, logical and or

1.2 JSX binding Properties

Tag attributes can also be bound with {}

You can’t add a class to the tag, because there are class conflicts in js, so you have to write className

If you want to add class attributes dynamically, use {}. If you want to add styles, you need to nest an object

<div className={"box title" + (this.state.active ? "active" : "")}>

<div style={{color:"red", fontSize:"50px"}}>
Copy the code

1.3 JSX Binding Events

React will Bind a call(undefined) to render. Bind call apply to render.

Constructor = this.click = this.click.bind(this)

The second option: the arrow function, never bound to this, finds its own upper scope, the class component itself

Third option (recommended) : simply pass in an arrow function and call the function that needs to be executed from the arrow function

() => {onclick(argument)}

1.4 Conditional Rendering

The first one is if else

The second is a ternary expression

The third uses logic and &&

1.5 JSX nature

Babel converts React. CreateElement (“div”,{className:”header”}, “hello world”) to JSX, so writing JSX code must rely on Babel

1.6 Virtual DOM Creation Process

The essence of react.createElement ultimately creates an object that forms a tree of JS objects, and rea.crea contains many other rea.crea objects.

The render function maps to the real DOM

1.7 Why use the Virtual DOM

It’s hard to keep track of changes in state

Manipulating the real DOM is poor performance: Document.CreateElement itself creates a very complex object

It can also cause backflow and redrawing of the browser

For example, if you add five Li’s after ul to the real DOM and loop through it, you’ll need to manipulate the real DOM five times.

React componentize

Componentization idea: tree structure

Class components: cannot write uppercase tags; uppercase tags are treated as components.

Class components must inherit from React.component

The class component must implement the Render function

2.1 Component Parameter Transfer

Functional components with ChildCpn. PropTypes = {name: propTypes. String. IsRequired} to declare type parameters,

Set the default with childcpn. defaultProps ={name:”why”}

Class components declare and set defaults with internal static propTypes={} and static defaultProps={}

If a parameter type is declared but not passed in, an error may be reported because NaN is not allowed in the react property {}

When sending custom events, note that the normal function this refers to undefined. There are three methods:

Using the arrow function, it looks for this itself

Pass events in child component tags using the arrow function {e => this.increment()}

Use bind to bind this

2.2 Cross-component communication

First: upload layer by layer, using props, after the subcomponent tag {… props}

Create a context instance

Const UserContext = React. CreateContext ({nickname: "aaaa", // default level: -1 // default})Copy the code

1.2. Use the Provider API to put the child components that need to be passed into a large container

<UserContext.Provider value={this.state}>   <Profile /></UserContext.Provider>
Copy the code

1.3. The child component uses its contextType API to refer to the context.context

ProfileHeader.contextType = UserContext; <h2> User name: {this.context.nickname}</h2><h2> User level: {this.context.level}</h2>Copy the code

Consumer: contextType consumer: contextType consumer: contextType consumer: contextType consumer: contextType consumer: contextType consumer: contextType consumer: contextType

Function ProfileHeader() {return (< usercontext.consumer > {value => {return (<div> <h2> {value. The nickname} < / h2 > < h2 > user level: {value. Level} < / h2 > < / div >)}} < / UserContext Consumer >)}Copy the code

If multiple contexts are nested, create the context first and wrap another layer in the App component. The child component that needs to call the value needs to return a callback.

return ( <UserContext.Consumer> { value => { return ( <ThemeContext.Consumer> { theme => { return ( <div> <h2 Style ={{color: theme. Color}}> User nickname: {value.nickname}</h2> <h2> User level: {value.level}</h2> <h2> color: {theme.color}</h2> </div> ) } } </ThemeContext.Consumer> ) } } </UserContext.Consumer> )Copy the code

3. SetState resolution

3.1 setState Asynchronous update

1, can significantly improve performance, because many setState will be called, each render function will be frequently called, the efficiency is very low

Ideally, multiple updates should be fetched, put into a queue, and then batch updated

2. If the state is updated synchronously, but the render function has not been executed (the virtual DOM and Diff algorithms are slower), then the state and props cannot be kept in sync.

3. If you want asynchronous results, the second parameter of setState is a callback that can be retrieved from inside, similar to nextTick

4, after the execution of setState, will execute componentDidUpdate life cycle, which can also take updated data

3.2 setState synchronization update

1, put in the timer will become synchronization

Native DOM becomes synced and composited events when placed in componentDidMount()

3.3 Data Combination

Assign ({},{this.state},{this.setState}). Update attributes will overwrite those that are not assigned

SetState is merged, multiple calls are merged into one

SetState ((prevState, props) => {return {}}), will not merge, will add

3.4 Component nested render calls

Typically, a parent component has multiple child components, but a method that calls one of them, such as a button click to perform setState, will re-invoke Render for the entire parent component, and each child will re-render, wasting performance

3.5 ShouldComponentUpdate

This life cycle can block the page’s render recall, use if judgment, and return true or false directly

shouldComponentUpdate(nextProps, nextState) { if (this.state.counter ! == nextState.counter){return true; } return false; }Copy the code

But for each component to call, there’s also if, if there are ten properties that change, there’s too much redundant code.

3.6 PureComponent

In a class Component, so when a class Component inherits, instead of inheriting Component, it inherits PureComponent, which automatically calls the shouldComponentUpdate lifecycle

The principle of PureComponent is to change props and state depending on whether the class component itself depends on it. If you change return True, re-render the render, and vice versa

ShouldComponentUpdate do not do deep comparison, very consume performance, do shallow comparison can be

3.7 Memo

In functional components, the memo is both a function and a higher-order component (which can operate on other components), using methods

Const MemoHeader = Memo (function component)Copy the code

Essentially the same as the PureComponent operation, depending on whether the functional component itself depends on and changes props and state, if return True is changed, re-render the render, and vice versa

3.8 SetState Immutable power

1. Don’t do it

    const newData = {name:"Tom", age:33}    this.state.friends.push(newData)    this.setState({friends:this.state.friends})
Copy the code

2. Recommended practices

    const newFriends = [...this.state.friends]    newFriends.push({name:"tom" , age:33})    this.setState({friends:newFriends})
Copy the code

The reason is that the second one regenerates a memory space, a bit like deep copy, in which shouldComponentUpdate is comparing two objects, and if it is the first one, it is comparing two identical objects.

4. Higher-order components

A higher-order component is essentially a function, and the parameter is a component, which is equivalent to packaging, strengthening components, enhancing reusability, which can be applied in login authorization, lifecycle hijacking to get component execution time, and so on.

The internal render content is normally the component passed in

render() { return <WrappedComponent {... this.props }/>}Copy the code

4.1 Ref forward

Class component: Passes arguments through ref, accepts them using the createRef function through props, and declares them in the parent component’s constructor

this.titleRef = createRef()
Copy the code

Function component: with the forwardRef function (which is essentially a high-order component, so the return value is a component), you can use ref in the forwardRef tag

const Profile = forwardRef(function(props, ref) {  return <p ref={ref}>Profile</p>})
Copy the code

4.2 Using Portal

The current component can be rendered at any current location and is mounted on root by default

class Modal extends PureComponent {  render() {    return ReactDOM.createPortal(      this.props.children,      document.getElementById("modal")    )  }}
Copy the code

4.3 Use of Fragments

You can delete unnecessary div nodes if they have no fragment attributes, but not if they do

return ( <Fragment key={item.name}>   <div>{item.name}</div>   <p>{item.age}</p>  <hr/> </Fragment>)
Copy the code

4.4 StrictMode

Turn on strict mode to trigger additional checks and warnings for descendant elements

1. Identify unsafe life cycles

2. Use outdated ref APIS such as string declarations of the form ref=”title”

Constructor is called twice, looking for side effects

4. Use the earlier abandoned findDOMNode method, which has been replaced by ref

5. Detect stale context apis

CSS styles in React

1. You can write local CSS that has its own scope and does not pollute other components

2. Write dynamic CSS, such as displaying different styles according to different booleans

5.1 Inline style

Advantages: Styles do not conflict, and states in state can be retrieved

Disadvantages: Need for hump identification, no code hints, code redundancy, can’t write pseudo-class elements

5.2 the common CSS

Write a separate CSS file and use it directly

Disadvantages: prone to conflicting overwrites and need to write multiple selectors to select a className in order to avoid conflicts

5.3 Css modules

Declare CSS file as style.module. CSS, className={} as object in render, className must be hump

Cons: Difficult to get dynamic styles, such as color in state, combined with inline styles

5.4 Css in JS (Recommended)

5.5 Styled – components

The tag template string is used to return a component, which can be used to replace the tag

const HYButton = styled.button` padding: 10px 20px; border-color: red; color: red; ` const HYPrimaryButton = styled(HYButton)` color: #fff; background-color: green; ` const HYInput = styled.input.attrs({ placeholder: "coderwhy", bColor: "red"})` background-color: lightblue; border-color: ${props => props.bColor}; color: ${props => props.color}; `Copy the code

The theme properties, introduced first, are defined in the parent component, and then the child component can be obtained directly by props

<ThemeProvider theme={{themeColor: "red", fontSize: "30px"}}/>export const TitleWrapper = styled.h2` text-decoration: underline; color: ${props => props.theme.themeColor}; font-size: ${props => props.theme.fontSize}; `Copy the code

5.6 Classnames library

Can be similar to vUE binding dynamic properties, as long as the return value is false will not be added to the tag property

const {isActive} = this.state; const isBar = false; const errClass = "error"; const warnClass = 10; <h2 className={"foo bar active title"}> I'm title 1</h2> <h2 className={"title" + (isActive? "Active" : "")} > I am heading 2 < / h2 > < h2 className = {" title", (isActive? "active" : Join (" ")}> I am heading 3</h2> {/* classnames library add class */} <h2 className="foo bar active title"> I am heading 4</h2> <h2 ClassName ={classNames("foo", "bar", "active", "title")}> I am heading 5</h2> <h2 className={classNames({"active": IsActive, "bar": isBar}, "title")}> I am title 6</h2> <h2 className={classNames("foo", errClass, warnClass, {"active": IsActive})}> I am heading 7</h2> <h2 className={classNames(["active", "title"])}> I am heading 8</h2> <h2 className={classNames(["active", "title"])}> "Title ", {"bar": isBar}])}>Copy the code

AntDesign Component library

Craco: Configuration change antD’s default blue theme style, change webPack configuration in craco.config.js

Change the import style file to less

const CracoLessPlugin = require('craco-less'); const path = require("path"); const resolve = dir => path.resolve(__dirname, dir); module.exports = { plugins: [ { plugin: CracoLessPlugin, options: { lessLoaderOptions: { lessOptions: { modifyVars: { '@primary-color': '#1DA57A' }, javascriptEnabled: true, }, }, }, } ], webpack: { alias: { "@": resolve("src"), "components": resolve("src/components") } }}Copy the code

7. Css transition animation

7.1 CssTransition # # # #Copy the code

Then write the corresponding style according to className. It is divided into three parts: Enter means enter, active means executing, End means after ending, and unmountOnExit means uninstall when hidden. If you need to animate a component for the first time, add the “Appear” property and write the corresponding animation in CSS.

import { CSSTransition } from 'react-transition-group'; <CSSTransition in={isShow} classNames="card" timeout={5000} unmountOnExit={true} appear/> .card-enter, .card-appear { opacity: 0; transform: scale(.6); }.card-enter-active, .card-appear-active { opacity: 1; transform: scale(1); transition: opacity 300ms, transform 300ms; }Copy the code

7.2 SwitchTransition

This is the toggle effect that cssTransition is used to show and hide directly.

The general usage is to bread a layer of cssTransition SwitchTransition. The timeout property is the time required to switch the class, and the timeout property in the CSS determines the animation execution time

<SwitchTransition mode="out-in"> <CSSTransition key={isOn ? "on": "off"} classNames="btn" timeout={1000}> <button onClick={e => this.setState({isOn: ! isOn})}> {isOn ? "on": "off"} </button> </CSSTransition></SwitchTransition> .btn-enter { opacity: 0; transform: translateX(100%); }.btn-enter-active { opacity: 1; transform: translateX(0); transition: opacity 1000ms, transform 1000ms; }.btn-exit { opacity: 1; transform: translateX(0); }.btn-exit-active { opacity: 0; transform: translateX(-100%); transition: opacity 1000ms, transform 1000ms; }Copy the code

7.3 TransitionGroup

The main function is to animate a set of elements, such as a list, by replacing div with TransitionGroup in the outermost layer.

Note: if the loop must be given a key, not adding it will cause the diff algorithm to add the class to the position removed after the diff algorithm comparison. For example, if the first of three data is deleted, the diff algorithm compares the first two to find the corresponding value, and the last one is deleted, so class animation is added to the last one.

<TransitionGroup> { this.state.names.map((item, index) => { return ( <CSSTransition key={item} timeout={500} classNames="item"> <div> {item} <button onClick={e => this.removeItem(index)}>-</button> </div> </CSSTransition>)}) }</TransitionGroup><button onClick={e => this.addName()}>+name</button> .item-enter {opacity: 0; transform: scale(.6); }.item-enter-active {opacity: 1; transform: scale(1); transition: opacity 300ms, transform 300ms; }.item-enter-done { color: red; }.item-exit {opacity: 1; transform: scale(1); }.item-exit-active {opacity: 0; transform: scale(.6); transition: opacity 300ms,transform 300ms}.item-exit-done {opacity: 0; }Copy the code

Redux state management

8.1 JavaScript Pure functions

A certain input must produce a certain output, for example, input 5, return 10, cannot change must be 10

When a function is executed, it cannot cause side effects, such as passing in an object and modifying the object

function sum(num1, num2) { return num1 + num2; } sum(20, 30); sum(20, 30); // This is pure function let foo = 10; function add(num) { return foo + num; } add(5); // 15 foo = 20; add(5); // 25 // is not a pure function, each input is 5 but the value is changed // Can the function above be changed to a pure function? const bar = 10; function add2(num) { return bar + num; } bar = 11; const baz = { count: 10 } function add3(num) { return baz.count + num } baz.count = 20; // It is not a pure function, the value of baz can be changed, input the same value may be different resultsCopy the code

All React components must protect their Props from being changed like pure functions

For example, if the parent component uses props to pass data to the child component, the child component can only use props, but cannot change it, for example, props.info.name=”why”

8.2 Redux’s three Principles

Single data source: The entire application state is stored in an object tree

State is read-only: the only way to change State must be to trigger an action. Do not change it elsewhere

Use pure functions to perform changes: The old state and action are linked together using the Reducer and the new state is returned when changes are made

8.3 Basic Usage process

1, define a unique store library, in which the index.js is the only exit, the job here is to import the total repository, other components can use directly import

import {createStore} from 'redux'import reducer from './reducer.js'​const store = createStore(reducer)​export default store
Copy the code

2. Declare the corresponding Reducer file, first declare the default state value, which reducer method is to perform corresponding operations (such as adding, deleting, changing and checking data, similar to callback) according to different action types of the reducer event. Remember to ensure pure functions by copying.

const defaultState ={ counter: 0}function reducer(state = defaultState, action){ switch(action.type){ case ADD_NUMBER: return {... state, counter: state.counter +action.num}; case SUB_NUMBER: return {... state, counter: state.counter -action.num}; default: return state }}Copy the code

3. In the actionCreators file, declare the corresponding distributed event action according to its type, and remember to return the object

export const addAction = (num) => {  return {    type:ADD_NUMBER,    num  }}​export const subAction = num => ({  type:SUB_NUMBER,  num})
Copy the code

4. Then dispatch the defined event directly to the required component, using store.dispatch, and listen for the result of the dispatch event with store.subscribe during the loaded declaration cycle

store.subscribe(() => { console.log(store.getState()); })store.dispatch(addAction(10))store.dispatch(addAction(10))store.dispatch(subAction(15))Copy the code

8.4 Using Redux in React

1. Introduce Redux and ActionCreator to the required component, and temporarily save the store state in the internal state of the component

    this.state = {      counter: store.getState().counter    }
Copy the code

2. In the declaration function, the corresponding action events are sent out with dispatch. These actions have been defined in ActionCreator

3. After events are distributed, corresponding methods will be implemented on reducer according to the type

Listen for state changes during the Didmount declaration cycle

 componentDidMount(){    this.unsubscribe = store.subscribe(() => {      this.setState({        counter:store.getState().counter      })    })  }
Copy the code

Unsubscribe listening during the Willunmount life cycle

  componentWillUnmount(){    this.unsubscribe()  }
Copy the code

8.5 Saving Back-end Data to Redux

Prerequisite: Encapsulate the corresponding React-redux

import { Provider } from 'react-redux'ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root')); // Add context to the total export file, passing storeCopy the code

Introduce and add high-level components of the CONNECT function where needed

import { connect } from 'react-redux'; export default connect(mapStateToProps, mapDispatchToProps)(Home);Copy the code

1. Use axios to request data in componentDidMount

2. From the default data in the Reducer, temporarily save the data that needs to be stored in the store

3. Declare action type in constants

4. Enter the tyoe variable name in the actionCreators account and set the corresponding action function, which returns an object

5. In the Reducer, add cases according to action type and return pure functions

6. In the component that requests the data, introduce the action that you just declared

Add a map to the object returned by mapDispatchToProps

  changeBanners(banners) {    dispatch(changeBannersAction(banners));  },  changeRecommends(recommends) {    dispatch(changeRecommendAction(recommends));  }
Copy the code

Store data requested with AXIOS in componentDidMount

  this.props.changeBanners(data.banner.list);  this.props.changeRecommends(data.recommend.list);
Copy the code

9. At this point, the data has been stored in the store state and can be used in another component

Const mapStateToProps = state => ({integration: state. Integration, recommends: state.Copy the code

8.6 Redux-Thunk Middleware

Request data is also a place for state management, so it is best to put it in redux. Add a middleware between the Dispatches and reducer to make the Dispatches directly return a function instead of an object

(1) Pass in the enhance function of middleware when creating a store; (2) use applyMiddleware to combine multiple middleware components and return an enhancer; 3. Pass enhancer as the second parameter to createStore;

const storeEnhancer = applyMiddleware(thunkMiddleware, sagaMiddleware); const store = createStore(reducer, storeEnhancer); // export const getHomeMultidataAction = (dispatch, getState) => {axios({url: "Http://123.207.32.32:8000/home/multidata"}). Then (res = > {const data = res. Data. The data; dispatch(changeBannersAction(data.banner.list)); dispatch(changeRecommendAction(data.recommend.list)); })} / / in the distributed component first, and then to request data in the distributed, then find the corresponding reducer processing componentDidMount () {this. Props. GetHomeMultidata (); }Copy the code

To use Redux-devTools, introduce Compose first, which requires a combination of the enhanced middleware

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({trace: true}) || compose;

const store = createStore(reducer, composeEnhancers(storeEnhancer));
Copy the code

8.7 Redux-Saga Middleware

Import createSagaMiddleware from 'redux-saga' // Import const sagaMiddleware = createSagaMiddleware() // Create middleware const StoreEnhancer = applyMiddleware(thunkMiddleware, sagaMiddleware) Function * mySaga() {// takeLatest takeEvery; // takeEvery: Yield all([takeLatest(FETCH_HOME_MULTIDATA, fetchHomeMultidata)), fetchHomeMultidata), ]); } // Listen for the corresponding action type, Function * fetchHomeMultidata(action) {const res = yield Axios. Get (" http://123.207.32.32:8000/home/multidata "); const banners = res.data.data.banner.list; const recommends = res.data.data.recommend.list; // yield put(changeBannersAction(banners)); // yield put(changeRecommendAction(recommends)); Yield All ([yield Put (changeBannersAction(clearly)), yield Put (changeRecommendAction(recommends))])} // Specifies the logic in the builder functionsCopy the code

8.8 CombineReducer

If we own a reducer, return an object that is a reducer

The disadvantage is that if the state in the action value is not changed, we need to return the same new reducer merged object, which wastes performance.

The advantage of combineReducer is that it will determine the action, return the new object if the data has changed, return the original object if the data has not changed

const reducer = combineReducers({  counterInfo: counterReducer,  homeInfo: homeReducer});
Copy the code

8.9 Unidirectional Data Flow

Both VUE and React have one-way data flow, which means data is passed through props.

UI View area -> Send an event -> Send Dispatch Execute Action -> Modify State -> Modify UI

One-way data flow in REdux:

An event occurs on the UI component -> dispatch an action -> action is passed to the reducer return the new state -> State changes cause the UI changes

Data cannot be passed across levels, such as directly store.getState() = newValue, which does not comply with the specification for one-way data flow

9. React Routing

Phase 1: Back-end routing

A page has its own corresponding URL, that is, URL. The URL will be sent to the server, which will match the URL through the re, and finally hand it to a Controller for processing. The Controller does all sorts of processing and eventually generates HTML or data that is returned to the front end. This completes an IO operation. This operation is called back-end routing. When we need to request different path content in the page, to the server for processing, the server render the whole page, and the page back to the customer. In this case, the rendered page does not need to load any SEPARATE JS and CSS, can be directly presented to the browser display, which is also conducive to SEO optimization.

Stage 2: anterior and posterior end separation

Static resources involved in each request are fetched from the static resource server; These resources include HTML+CSS+JS, and then render these resources back in the front end;

Then in another API server write interface request corresponding data, get the data to do a display

Stage 3: Single page rich application

The entire Web application actually has only one page, and when the URL changes, no new static resources are requested from the server; Instead, JavaScript listens for URL changes and renders new pages based on them. How can I apply urls and render pages? Front-end routing Front-end routing maintains the mapping between urls and rendered pages. Routing allows our frameworks (like Vue, React, Angular) to render different components based on different urls;

9.1 Principles of Front-end Routing

1, change the URL, but do not force the page refresh (a element is not allowed)

2, listen for URL changes, and change the content of the page

Hash routing

Window.addeventlistener ("hashchange", () => {switch (location.hash) {case "#/home": RouterViewel.innerhtml = "home"; break; Case "#/about": RouterViewel.innerhtml = "about"; break; default: routerViewEl.innerHTML = ""; }})Copy the code

The history of routing

el.addEventListener("click", e => { e.preventDefault(); Const href = el.getAttribute("href"); // Prevent default events const href = el.getattribute ("href"); history.pushState({}, "", href); urlChange(); // urlChange window.adDeventListener (' popState ',urlChange); // urlChange window.addeventListener (' popState ',urlChange); Function urlChange() {switch (location.pathname) {case "/home": RouterViewel.innerhtml = "home"; break; Case "/about": RouterViewel.innerhtml = "about"; break; default: routerViewEl.innerHTML = ""; }}Copy the code

9.2 the switch component

By default, components corresponding to routes whose paths are matched in the React-Router are rendered. In practice, however, we tend to want to have an exclusive mindset: once the first match is made, the subsequent matches should not continue; In this case, we can use the Switch to wrap all routes

NavLink specifies whether to display special content in the active case. Link specifies whether to add an additional active attribute

9.3 Click the button to redirect a route

If it is a subcomponent of the app, it has history,push,go and other properties because it is a component created by the app through routing. The subcomponent can get the history property through this.props. History

Js is the outer layer of the APP. There is no way to create components for the APP. In this case, we need to introduce withRouter

And in the outermost package Browser component, this.props. History can be called

10 and the React Hooks

10.1 useState

For simple states, the data is defined directly using deconstructed assignments

Note: If you want to add the value of state, you can’t push it, you have to copy it, because usestate determines whether state is updated to render, just like setState

<button onClick={e => setFriends([...friends, "Tom "])}>Copy the code

10.2 useEffect

Instead of a class component, some lifecycle execution

UseEffect (() => {console.log(" subscribe event "); // Similar to componentDidMount Life Cycle return () => {console.log(" unsubscribe "); ComponentWillUnmount}},[]) // The second argument is an array, for optimizationCopy the code

Normally, useEffect is re-executed whenever a component is rendered or updated, but some requests need to be executed only once, such as subscription events and network requests

The second argument is an array in which you can put the state you want to process, and only after the state is executed will the useEffect be called again

10.3 useContext

ContextType = MyContext; contextType = MyContext; Multiple contexts or shared contexts in functional components via myContext.consumer;

After using useContext

export default function Cpn1(props) {  const user = useContext(UserContext);  const theme = useContext(ThemeContext)  console.log(user, theme);  return (    <div>      <h2>ContextHookDemo</h2>      <h2>{user.name}</h2>      <h2>{user.age}</h2>    </div>  )}
Copy the code

Note: When the most recent < context. provider/> update is made to the component’s upper layer, the Hook will trigger a re-rendering using the latest Context value passed to MyContext Provider

10.4 useReducer

In some scenarios, if the processing logic of state is complicated, we can use useReducer to split it

Reducer is a pure function, so it needs to be copied

export default function Home() { // const [count, setCount] = useState(0); const [state, dispatch] = useReducer(reducer, {counter: 0}); Return (<div> <h2>Home current count: {state.counter}</h2> <button onClick={e => dispatch({type: "increment"})}>+1</button> <button onClick={e => dispatch({type: "decrement"})}>-1</button> </div> )} export default function reducer(state, action) { switch(action.type) { case "increment": return {... state, counter: state.counter + 1}; case "decrement": return {... state, counter: state.counter - 1}; default: return state; }}Copy the code

10.5 useCallback

The actual purpose of useCallback is to optimize the performance of functions

Usage scenario: useCallback is used to process functions in a component when they are passed to child components for callback

Const increment1 = () => {console.log(" execute increment1 function "); setCount(count + 1); } const increment2 = useCallback(() => {console.log(" execute increment2 function "); setCount(count + 1); }, [count]); Const HYButton = memo((props) => {console.log("HYButton re-render: "+ props. return <button onClick={props.increment}>HYButton +1</button>});Copy the code

At this point increment2, the value is the same, and the component will not be re-rendered after the memo shallow comparison

10.6 useMemo

The purpose is also to optimize performance, for state, or function, depending on the return value

If the child refers to the state of the parent, then the memo will be rerendered even if the package is passed, because every time the object is passed a new value, useMemo will be used

const info = { name: "why", age: 18 }; Const info = useMemo(() => {return {name: "why", age: 18}; } []); // Child components are not re-renderedCopy the code

10.7 useRef

1. Manipulate DOM

const titleRef = useRef();  const inputRef = useRef();  const testRef = useRef();  const testRef2 = useRef();​  function changeDOM() {    titleRef.current.innerHTML = "Hello World";    inputRef.current.focus();    console.log(testRef.current);    console.log(testRef2.current);  }​
Copy the code

UseEffect will be called after the button is clicked to execute render, which will pass the +10 count to numRef current, changing numRef will not re-render the interface

export default function RefHookDemo02() { const [count, setCount] = useState(0); const numRef = useRef(count); useEffect(() => { numRef.current = count; }, [count]) return (<div> {/* <h2>numRef: {numRef. Current}</h2> <h2>count: {count}</h2> */} <h2>count <button onClick={e => setCount(count +10)}>+10</button> </div>)}Copy the code

10.8 useImperativeHandle

UseImperativeHandle exposes only fixed operations, rather than the child exposing the entire REF to the parent: The Hook of useImperativeHandle is used to bind the object returned by the second parameter of useImperativeHandle to the ref passed in. So in the parent component, when you use inputref.current, you actually use the returned object; For example, IF I call focus, I can even call printHello

const HYInput = forwardRef((props, ref) => { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); }}), [inputRef]) return < input ref = {inputRef} type = "text" / >}) / / it is child components export default function UseImperativeHandleHookDemo () { const inputRef = useRef(); Return (<div> <HYInput ref={inputRef}/> <button onClick={e => inputref.current. Focus ()}> focus </button> </div>)}Copy the code

The parent component’s call to focus actually calls the useImperativeHandle function in the child component

10.9 useLayoutEffect

When render is done, execute in this hook again to determine if state has changed, if so render the latest state.

export default function EffectCounterDemo() { const [count, setCount] = useState(10); useEffect(() => { if (count === 0) { setCount(Math.random() + 200) } }, [count]); <button onClick={e => setCount(0)}> </div>)}Copy the code

The normal execution process is:

1. First click modify number to set 10set to 0

UseEffect hook is executed once the render function is called and count changes

Select count === 0 and return a random number

4, call render, count is changed and call useEffect, but this is not 0, directly render the page rendering result will first flash to 0, and then turn to random number, then change useEffect to useLayoutEffect, there will be no flash process

10.10 Customizing Hooks

A custom Hook is essentially an extraction of function code logic. Strictly speaking, it is not a React feature

Declared functions must begin with use

11. Function of Fiber

Fiber is an execution unit (shard). The browser loads all the js tasks in a single thread within a frame. The browser executes the Fiber shard whenever it has free time, according to requestIdleCallback().