In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces the total number of hooks in react, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.
There are 9 hooks:useState, useEffect, useContext, useReducer, useCallback, useMemo, useRef, useImperativeHandle and useLayoutEffect in react.
The operating environment of this tutorial: Windows7 system, react17.0.1 version, Dell G3 computer.
React Hooks (total of 9)
In the world of React, there are container components and UI components. Before the emergence of React Hooks, we can use functions and stateless components to display UI in UI components, but for container components, function components are powerless. We rely on class components to obtain data, process data, and pass parameters down to UI components for rendering. In my opinion, using React Hooks has the following advantages over previous class components:
The code is more readable, and the code logic of the same function is split into different life cycle functions, which makes it difficult for developers to maintain and iterate. The functional code can be aggregated through React Hooks to facilitate reading and maintenance.
The level of the component tree becomes shallow. In the original code, we often use HOC/render props and other methods to reuse the state of the component and enhance the functions, which undoubtedly increase the number of layers of the component tree and rendering. In React Hooks, these functions can be realized through the powerful custom Hooks.
React has introduced new React Hooks features in v16.8, although the community doesn't have best practices on how to build complex applications based on React Hooks (at least I haven't). By reading a lot of articles in the community on this, here are ten examples to help you understand and be proficient in using most of the features of React Hooks.
1. UseState saves the component state
In the class component, we use this.state to save the component state and modify it to trigger the component to re-render. For example, the following simple counter component is a good explanation of how class components work:
Import React from "react"; class App extends React.Component {constructor (props) {super (props); this.state = {count: 0, name: "alife"};} render () {const {count} = this.state; return (
Count: {count} this.setState ({count: count + 1})} > + this.setState ({count: count-1})} >-
);}}
A simple counter component is completed, and in the function component, since there is no dark magic of this, React uses useState to help us save the state of the component.
Import React, {useState} from "react"; function App () {const [obj, setObject] = useState ({count: 0, name: "alife"}); return (Count: {obj.count} setObject ({. Obj, count: obj.count + 1})} > + setObject ({... obj, count: obj.count-1})} >-
);}
An array with default state and change state functions is returned by passing in the useState parameter. Change the original state value by passing a new state to the function. It is worth noting that useState does not help you deal with state. Compared with setState non-overlay update status, useState overlay update status requires developers to handle their own logic. (code above)
It seems that with a useState, function components can have their own state, but that's not enough.
2. Side effects of useEffect treatment
Function components can save state, but there is nothing you can do about side effects for asynchronous requests, so React provides useEffect to help developers deal with the side effects of function components. Before introducing the new API, let's take a look at how class components do it:
Import React, {Component} from "react"; class App extends Component {state = {count: 1}; componentDidMount () {const {count} = this.state; document.title = "componentDidMount" + count; this.timer = setInterval (() = > {this.setState (({count}) = > ({count: count + 1}));}, 1000);} componentDidUpdate () {const {count} = this.state Document.title = "componentDidMount" + count;} componentWillUnmount () {document.title = "componentWillUnmount"; clearInterval (this.timer);} render () {const {count} = this.state; return (
Count: {count} clearInterval (this.timer)} > clear
);}}
In the example, the component updates the component state every second, and each time the update is triggered, the update of the document.title (side effect) is triggered, while the document.title is modified when the component is unloaded (similar to clearing).
As you can see from the example, some repetitive function developers need to rewrite on componentDidMount and componentDidUpdate, but it is completely different if they use useEffect.
Import React, {useState, useEffect} from "react"; let timer = null;function App () {const [count, setCount] = useState (0); useEffect () = > {document.title = "componentDidMount" + count;}, [count]); useEffect () = > {timer = setInterval (() = > {setCount (prevCount = > prevCount + 1);}, 1000) / / be sure to pay attention to this order: / / tell react to call return () = > {document.title = "componentWillUnmount"; clearInterval (timer);};}, []) after the next re-rendering of the component and before the next setInterval execution above; return (
Count: {count} clearInterval (timer)} > clear
);}
We use useEffect to rewrite the above example, the first parameter of useEffect receives a function, which can be used to do some side effects such as asynchronous requests, modifying external parameters, etc., while the second parameter is called dependencies, which is an array. If the value in the array changes, it will trigger the execution of the function in the first parameter of useEffect. The return value, if any, is called before the component is destroyed or the function is called.
1. For example, in the first useEffect, it is understood that once the count value changes, the documen.title value is modified.
two。 An empty array [] is passed in the second useEffect, which is triggered only when the component is initialized or destroyed. It is used instead of componentDidMount and componentWillUnmount.
In another case, the second argument is not passed, that is, the useEffect only receives the first function argument, which means that no parameter changes are listened for. Each time the DOM is rendered, the functions in the useEffect are executed.
Based on this powerful Hooks, we can simulate and encapsulate other lifecycle functions, such as componentDidUpdate code is very simple
Function useUpdate (fn) {/ / useRef create a reference const mounting = useRef (true); useEffect () = > {if (mounting.current) {mounting.current = false;} else {fn ();});}
Now that we have useState management state, useEffect processing side effects, and asynchronous logic, learning these two tricks is sufficient for most class component usage scenarios.
3. UseContext reduces the level of components
The two most basic API, useState and useEffect, are introduced above. The next useContext is encapsulated by React to handle multi-level data transfer. In previous component trees, when cross-level ancestral components want to pass data to grandson components, in addition to layer by layer of props, we can also use React Context API to do this for us, to give a simple example:
Const {Provider, Consumer} = React.createContext (null); function Bar () {return {color = >
{color}
};} function Foo () {return;} function App () {return ();
Through the syntax of React createContext, you can pass data to Bar across the Foo component in the APP component. In React Hooks, we can use useContext to modify it.
Const colorContext = React.createContext ("gray"); function Bar () {const color = useContext (colorContext); return
{color}
;} function Foo () {return;} function App () {return ();}
What is passed to useContext is context, not consumer, and the return value is the data you want to transmit transparently. The usage is simple, and the problem of Consumer multistate nesting can be solved by using useContext.
Function HeaderBar () {return ({user = > {notifications = > Welcome back, {user.name}! You have {notifications.length} notifications. });}
UseContext, on the other hand, becomes very concise, more readable and does not increase the depth of the component tree.
Function HeaderBar () {const user = useContext (CurrentUser); const notifications = useContext (Notifications); return (Welcome back, {user.name}! You have {notifications.length} notifications. );} 4, useReducer
UseReducer this Hooks is almost exactly the same as Redux/React-Redux in use, the only thing missing is the inability to use the middleware provided by redux. We rewrite the above timer component to useReducer
Import React, {useReducer} from "react"; const initialState = {count: 0}; function reducer (state, action) {switch (action.type) {case "increment": return {count: state.count + action.payload}; case "decrement": return {count: state.count-action.payload}; default: throw new Error ();} function App () {const [state, dispatch] = useReducer (reducer, initialState) Return (Count: {state.count} dispatch ({type: "increment", payload: 5})} > + dispatch ({type: "decrement", payload: 5})} > -);}
The usage is basically the same as Redux, and the usage is very simple, which can be regarded as providing a Redux version of mini.
5. UseCallback memory function
In class components, we often make the following mistakes:
Class App {render () {return
{console.log ('do something');}} / >
;}}
What's the harm of writing like this? Once the props or status of the App component changes, re-rendering will be triggered. Even if it is not related to the SomeComponent component, each render will generate new style and doSomething (because style and doSomething point to different references before and after re-render), so it will cause SomeComponent to re-render. If SomeComponent is a large component tree, such Virtual Dom comparison is obviously wasteful, and the solution is very simple, to extract the parameters into variables.
Const fontSizeStyle = {fontSize: 14}; class App {doSomething = () = > {console.log ('do something');} render () {return
;}}
In the class component, we can also store the function through the this object, but there is no way to mount it in the function component. So the function component will re-render the subcomponent if there is a transfer function each time it is rendered.
Function App () {const handleClick = () = > {console.log ('Click happened');} return Click Me;}
One more thing here, the functional component is understood as the syntax sugar of the render function of the class component, so every time it is re-rendered, all the code within the functional component will be re-executed. So each render,handleClick in the above code is a new reference, so the props.onClick passed to the SomeComponent component changes all the time (because it is a new reference each time), so it is said that in this case, the function component will rerender the subcomponent if it has a pass function each time it is rendered.
With useCallback, it's different. You can get a memorized function through useCallback.
Function App () {const memoizedHandleClick = useCallback (() = > {console.log ('Click happened')}, []); / / empty array represents that the function will not change return Click Me; under any circumstances.
As an old rule, the second parameter is passed in an array, and once each item in the array changes, useCallback returns a new memory function to render later.
In this way, unnecessary VDOM rendering can be effectively avoided as long as the subcomponents inherit PureComponent or use React.memo.
6. UseMemo memory component
The function of useCallback can be replaced by useMemo, if you want to return a memory function by using useMemo.
UseCallback (fn, inputs) is equivalent to useMemo (() = > fn, inputs).
So the previous example using useCallback can be rewritten using useMemo:
Function App () {const memoizedHandleClick = useMemo (() = > () = > {console.log ('Click happened')}, []); / / the empty array represents that the function will not change return Click Me; under any circumstances.
The only difference is that * * useCallback will not execute the first parameter function, but will return it to you, while useMemo will execute the first function and return the result of the function execution to you. * * so in the previous example, you can return handleClick to store the function.
Therefore, useCallback often memorizes the event function, generates the memorized event function and passes it to the subcomponents. On the other hand, useMemo is more suitable to get a definite value by function calculation, such as memory component.
Function Parent ({a, b}) {/ / Only re-rendered if `a`changes: const child1 = useMemo (() = >, [a]); / / Only re-rendered if `b`changes: const child2 = useMemo (() = >, [b]); return ({child1} {child2})}
Child1/child2 will only re-render when the ASCUB changes. As you can see from the example, the update of the subcomponent is triggered only when the value of the second parameter array changes.
7. UseRef saves reference values
UseRef is similar to createRef in that it can be used to generate references to DOM objects. Take a simple example:
Import React, {useState, useRef} from "react"; function App () {let [name, setName] = useState ("Nate"); let nameRef = useRef (); const submitButton = () = > {setName (nameRef.current.value);}; return (
{name}
Submit
);}
If the value returned by useRef is passed to the component or the ref property of the DOM, you can access the component or the real DOM node through the ref.current value. The point is that the component is also accessible, so that you can do some operations on the DOM, such as listening for events, and so on.
Of course, useRef is much more powerful than you think. UseRef functions a bit like class properties, or you want to record some values in the component, and these values can be changed later.
The features of Capture Value can be bypassed with useRef. You can assume that ref maintains a unique reference in all Render processes, so all assignments or values to ref get only a final state, and there is no isolation between each Render.
There are features of Capture Value in React Hooks:
Function App () {const [count, setCount] = useState (0); useEffect () = > {setTimeout (()) = > {alert ("count:" + count);}, 3000);}, [count]); return (
You clicked {count} times
SetCount (count + 1)} > increase count setCount (count-1)} > decrease count
);}
First click to add button, then click to decrease button,3 seconds, first alert 1, then alert 0, instead of alert twice 0. This is the feature of the so-called capture value. In the class component, the modified value is output after 3 seconds, because * * message is mounted on the this variable, it retains a reference value * *, and the access to the this attribute will get the latest value. At this point, you should understand that useRef can effectively circumvent the Capture Value feature in React Hooks by creating a reference.
Function App () {const count = useRef (0); const showCount = () = > {alert ("count:" + count.current);}; const handleClick = number = > {count.current = count.current + number; setTimeout (showCount, 3000);}; return (
You clicked {count.current} times
HandleClick (1)} > increase count handleClick (- 1)} > decrease count
);}
As long as you change the object that assigns and takes values to useRef instead of useState, you can bypass the capture value feature and get the latest values in 3 seconds.
8. UseImperativeHandle transparently transfers Ref
UseImperativeHandle is used to enable the parent component to obtain the index within the child component
Import React, {useRef, useEffect, useImperativeHandle, forwardRef} from "react"; function ChildInputComponent (props, ref) {const inputRef = useRef (null); useImperativeHandle (ref, () = > inputRef.current); return;} const ChildInput = forwardRef (ChildInputComponent); function App () {const inputRef = useRef (null); useEffect () = > {inputRef.current.focus ();}, []); return (
);}
In this way, the App component can get the DOM node of the input of the child component.
9. Side effects of useLayoutEffect synchronous execution
In most cases, using useEffect can help us deal with the side effects of components, but if you want to call some side effects synchronously, such as an operation on DOM, you need to use the side effects in useLayoutEffect,useLayoutEffect that will be synchronized after the DOM update.
Function App () {const [width, setWidth] = useState (0); useLayoutEffect () = > {const title = document.querySelector ("# title"); const titleWidth = title.getBoundingClientRect (). Width; console.log ("useLayoutEffect"); if (width! = = titleWidth) {setWidth (titleWidth);}}); useEffect (() = > {console.log ("useEffect");}); return (
Hello {width}
);}
In the above example, useLayoutEffect will synchronize the trigger function after the render,DOM update, which is better than the useEffect asynchronous trigger function.
1. What is the difference between useEffect and useLayoutEffect?
To put it simply, the timing of the call is different, and the useLayoutEffect is the same as the original componentDidMount&componentDidUpdate. The code called synchronously after the react completes the DOM update will block the page rendering. UseEffect is the code that will not be called until the entire page is rendered.
Official recommendation to give priority to useEffect
However, we recommend starting with useEffect first and only trying useLayoutEffect if that causes a problem.
In actual use, if you want to avoid page jitter (modifying DOM in useEffect is likely to occur), you can put the code that needs to operate DOM in useLayoutEffect. About using useEffect to cause page jitter.
However, a warning will appear when useLayoutEffect is rendered on the server, so to eliminate it, you have to use useEffect instead or postpone the rendering time.
Thank you for reading this article carefully. I hope the article "how many hooks in react" shared by the editor will be helpful to you. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.