We know that when the parent component is re-rendered, all of it (state, local variables, etc.) is new. If a child depends on an object variable of the parent, the child gets the new object regardless of whether the object changes, invalidating the diff corresponding to the child and reexecuting that part of the logic. In the example below, our side effects dependency contains object parameters passed in by the parent component, which triggers a data request each time the parent component is updated.
function Info({ style, }) {
console.log('Info renders');
useEffect(() = > {
console.log('Reload data'); // Data is reloaded every time a rerender occurs
}, [style]);
return (
<p style={style}>This is the text in Info</p>
);
}
function Page() {
console.log('Page rendered ');
const [count, setCount] = useState(0);
const style = { color: 'red' };
// count +1 causes Page to be re-rendered, which in turn causes Info to be re-rendered
return (
<div>
<h4>Count: {count}</h4>
<button onClick={()= > setCount(count + 1)}> +1 </button>
<Info style={style} />
</div>
);
}
Copy the code
React Hooks provide a solution. UseMemo allows us to cache incoming objects and recalculate and update them only when dependencies change.
function Page() {
console.log('Page rendered ');
const [color] = useState('red');
const [count, setCount] = useState(0);
const style = useMemo(() = > ({ color }), [color]); // Style changes only when color changes substantially
// count +1 causes Page to be re-rendered, which in turn causes Info to be re-rendered
// However, since style is cached, reloading of data in Info will not be triggered
return (
<div>
<h4>Count: {count}</h4>
<button onClick={()= > setCount(count + 1)}> +1 </button>
<Info style={style} />
</div>
);
}
Copy the code
useCallback
React Hooks support friendlier use of context for state management, avoid loading irrelevant parameters to the middle layer when there are too many layers; The other is to allow functions to participate in the data flow and avoid passing redundant parameters to the underlying components.
UseContext is one of the core modules of hooks that retrieve the current value of the context passed to them for cross-layer communication. React: When the context value changes, all components that use the context will be rerendered. In order to avoid redrawing irrelevant components, we need to construct the context properly. For example, starting from the new mindset mentioned in section 1, we need to organize the context by the degree of relevence of the states and store the related states in the same context.
In the past, if a parent component used the same data request method, getData, and that method depended on a query value passed in from above, the query and getData methods were passed together to the child component, which used the query value to decide whether to re-execute getData.
class Parent extends React.Component {
state = {
query: 'keyword',}getData() {
const url = `https://mocks.alibaba-inc.com/mock/fO87jdfKqX/demo/queryData.json?query=The ${this.state.query}`;
// Request data...
console.log('Request path is:${url}`);
}
render() {
return (
// Pass a query value that the child component does not render
<Child getData={this.getData} query={this.state.query} />); }}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) { // Only the query value can be used to determine
this.props.getData(); }}render() {
return (
// ...); }}Copy the code
In React Hooks useCallback allows us to cache a function and update the function if and only if the dependency changes. This enables on-demand loading with useEffect in the child components. With hooks, functions are no longer just a method, but can participate as a value in the application’s data flow.
function Parent() {
const [count, setCount] = useState(0);
const [query, setQuery] = useState('keyword');
const getData = useCallback(() = > {
const url = `https://mocks.alibaba-inc.com/mock/fO87jdfKqX/demo/queryData.json?query=${query}`;
// Request data...
console.log('Request path is:${url}`);
}, [query]); GetData is updated if and only if query changes
// A change in the count does not cause the Child to rerequest the data
return (
<>
<h4>Count: {count}</h4>
<button onClick={()= > setCount(count + 1)}> +1 </button>
<input onChange={(e)= > {setQuery(e.target.value)}} />
<Child getData={getData} />
</>
);
}
function Child({ getData }) {
useEffect(() = > {
getData();
}, [getData]); // Functions can participate in the data flow as dependencies
return (
// ...
);
}
Copy the code
Reference: What exactly are we talking about when we talk about hooks