When the value of the context of the react interview changes, whether all internal subcomponents change

test code

// context
const state = {
    
    
    a: 1,
    b: 1,
}
const context = createContext(state);

export default context;
// A组件
const A = () => {
    
    
    const {
    
     a } = useContext(context);
    return (<div>{
    
    a}</div>)
}
export default A;

// B组件
const B = () => {
    
    
    const {
    
     b } = useContext(context);
    return (<div>{
    
    b}</div>)
}
export default B;

// C组件, 不引用context
const C = () => {
    
    
    return (<div>cccc</div>)
}
export default C;

// APP.js
function App() {
    
    
	const [a, setA] = useState(-1);
	return (
		<div>
			<Context.Provider value={
    
    {
    
    
				a,
				b
			}}>
	          <A />
	          <B />
	          <C />
	      	</Context.Provider>
	      	<button onClick={
    
    () => setA(a+1)}>+++</button>
      	</div>
     );

Ask, when the button is clicked, which of the three components ABC will be refreshed?


The answer is that all three will be refreshed, because the state in the App component has changed, causing all components to be refreshed. So it is impossible to know whether the context has any effect on B and C components.

In order to solve the state update of the parent component and cause the update of the child component, we need to add the memo method to the export default of the three components of ABC, and the second parameter is PropsAreEqual, so that it returns true directly.

After transformation, it is:

// A组件
// ...
export default memo(A, () => true);

// B组件
// ...
export default memo(B, () => true);

// C组件, 不引用context
// ...
export default memo(C, () => true);

At this point, click the button again, who will trigger the update.


The answer is that AB will trigger an update, but C will not.

But we only updated the value of a, why is the B component that does not use a updated?

It is because they share a context, and its value is an object, and a new object will be regenerated every time, so the B component thinks that the context has been updated, so it will trigger rendering.

So it can be seen that as long as the value of context changes, all the uses of useContext(context) will be updated.

What if we add a D component to the C component and let the D component refer to the context?

// C组件, 不引用context
const C = () => {
    
    
    return (<div>
	    cccc
	    <D/>
    </div>)
}
export default memo(C, () => true);
// D组件
const D = () => {
    
    
    const {
    
     b } = useContext(context);
    return (<div>{
    
    b}</div>)
}
export default memo(D, () => true);

Will C trigger an update when the button is clicked?

The answer is no, ABD has been updated, but C has not been updated. Further verified his conjecture.

What should I do if I don't want BD to change because of a change?

Then disassemble b from the state and recreate a bContext!

// App组件改为:
function App() {
    
    
const [a, setA] = useState(-1);
const [b, setB] = useState(-1);
	return (
		<div>
			<Context.Provider value={
    
    {
    
    a}}>
			  <BContext.Provider value={
    
    {
    
    b}}>
			    <A />
			    <B />
			    <C />
			  </BContext.Provider>
			</Context.Provider>
			<button onClick={
    
    () => setA(a+1)}>++a</button>
			<button onClick={
    
    () => setA(b+1)}>++b</button>
		</div>
	)
}
// B组件和D组件都更新为引用bContext
import bContext from "./context/b"
// ...
const {
    
     b } = useContext(bContext);
// ...

At this point, do you think the BD will be updated when the a button is clicked?

The answer is that it will be updated, why?

Because the value of BContext is a new object every time, he thinks it is always changing, so if you want to pass an object, the best way is to redefine one with useMemo in the outer layer. {a} is the same.

// App改为
 const aVal = useMemo(() => ({
    
     a }), [a])
 const bVal = useMemo(() => ({
    
     b }), [b])
 
<Context.Provider value={
    
    aVal}>
	<BContext.Provider value={
    
    bVal}>
	   <A />
	   <B />
	   <C />
	 </BContext.Provider>
</Context.Provider>

Updating the value of a at this time will not affect the BD component, only the A component will be updated. At the same time, updating the value of b will not trigger the update of A component, only BD update. C will not be affected by the update of the two values ​​​​of a and b.

So far, it can be concluded that when the value of the context is updated, it will only affect the components using the context, and will not affect other components (provided that the control is done in memo.)

Guess you like

Origin blog.csdn.net/qq_28992047/article/details/132073796