In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "what is the method of mastering Hooks". In daily operation, I believe that many people have doubts about mastering the method of Hooks. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts of "what is the method of mastering Hooks?" Next, please follow the editor to study!
During this period of development with React, my biggest feeling is that "this is the best and worst era of React"! the "good" is that hooks has opened up a different development model, which requires more attention to the dependency relationship between data in the way of thinking, at the same time, it is easier to write, which generally improves the efficiency of development. The "bad" is that the class components and function components often coexist in the project, while the class components are dominated by the idea of class programming, and the development process pays more attention to the rendering cycle of the whole component, and it is often necessary to jump left and right between the two modes of thinking when maintaining the project. that's not the worst part.
One day, Lao Wang asked me, "you have been 'glancing at the articles of hooks every week'. What points do you think hooks can easily cause memory leakage?" It caused me to think deeply (because my mind went blank). We've been talking about hooks. What exactly are we talking about? Although there is a lot of discussion about hooks in the community, it is more about how to use popular science Hooks API, or how to compare it with class component life cycle and redux, and the lack of discussion and consensus on hooks best practices. I think this is the "worst" point. Today, we might as well discuss the changes brought about by hooks and how we can embrace them.
Note "A glimpse of the week" is a column that translates and shares fresh goods on the extranet within the team.
Since the release of React 16.8, Hooks has been deeply rooted in the hearts of the people, and it has brought about three biggest changes: the change of thinking mode, the change of scope during rendering and the change of data flow.
Thinking mode
From the official website of React, we can see that the design motivation of Hooks is to simplify the reuse of state logic between components, to enable developers to abstract the associated logic into smaller functions, and to reduce cognitive costs without understanding the suffocating this in JS Class. Under such motivation, hooks weakens the concept of component life cycle and strengthens the dependency between state and behavior, which can easily lead us to focus more on "what to do" rather than "how to do" [1].
Suppose there is a scenario in which the component Detail relies on the query parameters passed in by the parent component for data requests, then we need to define an asynchronous request method getData whether it is based on the class component or Hooks. The difference is that in the development mode of class components, what we want to think about is more inclined to "how to do": request data when the component is loaded, compare the old and new query values when the component is updated, and call the getData function again if necessary.
Class Detail extends React.Component {state = {keyword:',} componentDidMount () {this.getData ();} getSnapshotBeforeUpdate (prevProps, prevState) {if (this.props.query! = = prevProps.query) {return true;} return null;} componentDidUpdate (prevProps, prevState, snapshot) {if (snapshot) {this.getData () }} async getData () {/ / this is the code for asynchronously requesting data console.log (`data requested, parameter: ${this.props.query} `); this.setState ({keyword: this.props.query})} render () {return ()
Key words: {this.state.keyword}
);}}
In functional components that apply Hooks, we think about "what to do": different query values, showing different data.
Function Detail ({query}) {const [keyword, setKeyword] = useState (''); useEffect () = > {const getData = async () = > {console.log (`data request, parameter: ${query} `); setKeyword (query);} getData ();}, [query]); return (
Key words: {keyword}
);}
Under this guidance, the thinking mode of developers in the coding process should also be changed, and the synchronous relationship between data and data, data and behavior should be considered. This pattern can more succinctly combine the relevant code together, and even abstract into a custom hooks, achieving the sharing of logic, which seems to have the flavor of plug-and-pull programming.
Although Dan Abramov mentioned in his blog that thinking and deciding when to perform side effects from a lifecycle perspective is countertrend [2], knowing the timing of each hooks's execution during component rendering helps us to maintain a consistent understanding with React and be able to focus more accurately on "what to do". Donavon combs and compares the hooks paradigm with the lifecycle paradigm [3] in the form of a chart, which can help us understand how hooks works in components. Every time the component is updated, the component function will be called again to generate a new scope, which also puts forward new coding requirements for us developers.
Scope
In a class component, once the component is instantiated, it has its own scope, which remains the same from creation to destruction. Therefore, throughout the lifecycle of the component, the internal variables always point to the same reference during each rendering, so we can easily get the latest status value through this.state in each rendering, or we can use this.xx to get the same internal variable.
Class Timer extends React.Component {state = {count: 0, interval: null,} componentDidMount () {const interval = setInterval (()) = > {this.setState ({count: this.state.count + 1,})}, 1000); this.setState ({interval});} componentDidUnMount () {if (this.state.interval) {clearInterval (this.state.interval) }} render () {return (counter: {this.state.count});}}
In Hooks, the relationship between render and state is more like closures and local variables. Each time you render, a new state variable is generated, to which React writes the state value of the current rendering and remains the same during the current rendering. That is, each rendering is independent of each other and has its own status value. Similarly, the functions, timers and side effects in the component are also independent, and the internal access is also the status value of the current rendering, so we often encounter situations where the latest values cannot be read in the timer / subscriber.
Function Timer () {const [count, setCount] = useState (0); useEffect () = > {const interval = setInterval (()) = > {setCount (count + 1); / / always only 1}, 1000); return () = > {clearInterval (interval);}}, []); return (counter is: {count});}
If we want to get the latest value, there are two solutions: one is to use the lambada form of setCount to pass in a function with more than one state value as a parameter, and the other is to store the latest value in its current property with the help of the useRef hook.
Function Timer () {const [count, setCount] = useState (0); useEffect () = > {const interval = setInterval (()) = > {setCount (c = > c + 1);}, 1000); return () = > {clearInterval (interval);}, []); return (counter: {count});}
In the hook-flow diagram, we can see that when the parent component is re-rendered, all of its (states, local variables, etc.) are new. Once the child component depends on an object variable of the parent component, the child component gets the new object regardless of whether the object changes or not, thus invalidating the diff corresponding to the child component, and will still re-execute that part of the logic. In the following example, our side effect dependency contains the object parameters passed in by the parent component, and a data request is triggered each time the parent component is updated.
Function Info ({style,}) {console.log ('Info rendering occurs'); useEffect (() = > {console.log ('reload data'); / / data is reloaded every time a re-rendering occurs, [style]); return (this is the text in Info
);} function Page () {console.log ('Page rendering'); const [count, setCount] = useState (0); const style = {color: 'red'}; / / counter + 1 causes Page to re-render, which in turn causes Info to re-render return (count: {count} setCount (count + 1)} > + 1);}
React Hooks provides us with a solution, and useMemo allows us to cache incoming objects and recalculate and update corresponding objects only when dependencies change.
Function Page () {console.log ('Page rendering'); const [color] = useState ('red'); const [count, setCount] = useState (0); const style = useMemo (() = > ({color}), [color])) / / only when the color changes substantially, the style will change / / when the counter + 1 causes the re-rendering of the Page, which in turn causes the re-rendering of the Info / but because the style is cached, it will not trigger the data in the Info to reload the return (count: {count} setCount (count + 1)} > + 1);}
Data stream
There are two changes brought about by React Hooks in the data flow: one is to support more friendly use of context for state management to avoid carrying irrelevant parameters to the middle layer when there are too many levels; the other is to allow functions to participate in the data flow to avoid passing redundant parameters to the lower-level components.
As one of the core modules of hooks, useContext can obtain the current value of the incoming context, so as to achieve the purpose of cross-layer communication. The official website of React is described in detail. It is important to note that once the value of context changes, all components that use the context will be re-rendered. In order to avoid extraneous component redrawing, we need to build the context reasonably, for example, starting from the new mode of thinking mentioned in the first section, organizing the context according to the relevance of the state, and storing the related state in the same context.
In the past, if the parent and child components used the same data request method getData, and the method depended on the query value passed in by the upper layer, it was usually necessary to pass the query and getData methods to the child component, and the child component decided whether to re-execute the getData by judging the query value.
Class Parent extends React.Component {state = {query: 'keyword',} getData () {const url = `data / / request data. Console.log (`request path is: ${url} `);} render () {return (/ / passed a query value that the subcomponent does not render);}} class Child extends React.Component {componentDidMount () {this.props.getData () } componentDidUpdate (prevProps) {/ / if (prevProps.getData! = = this.props.getData) {/ / this condition is always true / / this.props.getData (); / /} if (prevProps.query! = = this.props.query) {/ / can only be judged by query value this.props.getData () }} render () {return (/ /...);}}
In React Hooks, useCallback allows us to cache a function and update it when and only if the dependency changes. This allows us to load on demand in conjunction with useEffect in the subcomponents. Through the cooperation of hooks, the function is no longer just a method, but can participate in the data flow of the application as a value.
Function Parent () {const [count, setCount] = useState (0); const [query, setQuery] = useState ('keyword'); const getData = useCallback (() = > {const url = `data / / request data. Console.log (`request path is: ${url} `);}, [query]); / / if and only if query changes, getData updates / / the change in count value does not cause Child to re-request data return (count value: {count} setCount (count + 1)} > + 1 {setQuery (e.target.value)}} / >) } function Child ({getData}) {useEffect (() = > {getData ();}, [getData]); / / function can participate in return (/ /...) in the data flow as a dependency;}
Summary
Going back to the original question: "what are the points that can easily cause memory leaks in hooks?" I understand that the risk of memory leaks lies in the scope changes brought about by hooks. Because each rendering is independent, once a side effect refers to a local variable and is not released in time when the component is destroyed, it is easy to cause a memory leak. On how to make better use of hooks, Sandro Dolidze listed a checkList [4] in his blog, which I think is a good suggestion to help us write the right hooks application.
Follow the Hooks rules
Do not use any side effects in the function body, but put it into useEffect to execute
Unsubscribe / process / destroy all used resources
Preferred function updates for useReducer or useState to prevent reading and writing the same value in the hook
Instead of using mutable variables in the render function, use useRef
If the life cycle of content saved in useRef is smaller than that of the component itself, do not release this value when processing resources
Beware of dead loops and memory leaks
When you need to improve performance, you can memoize functions and objects
Set dependencies correctly (undefined = > each render; [a, b] = > when an or b changes; [] = > execute only once)
Use custom hooks. Exe in reusable use cases.
At this point, the study of "what is the method of mastering Hooks" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
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.