我想知道如何避免对没有收到component
但使用props
的孩子useContext
进行不必要的更新。
我已将React.memo
添加到Child2 component
中,以便进行一些演示测试。
如您所见,当我更改input
值(使用context
将数据传递到child1
时,Child2
不会重新呈现,因为{{ 1}}可以防止这种行为。
如何在Child1中也防止不必要的渲染?我知道React.memo不能按需使用React.memo
,并且使用props
不会发生,因为没有context
会传递给此props
< / p>
component
App.js
import React, {useState} from 'react';
import './App.css';
import Child1 from "./Child1";
import Child2 from "./Child2";
import SillyContext from './context'
function App() {
const [name, setName] = useState('Radha');
const [count, setCount] = useState(0)
const increaseCount = () => {
setCount(prevState => prevState + 1)
}
return (
<div className="App">
<Child2 count={count}/>
<button onClick={increaseCount}>Increase</button>
<input type="text" value={name} onChange={(event => setName(event.target.value))}/>
<SillyContext.Provider value={{name}}>
<Child1/>
</SillyContext.Provider>
</div>
);
}
export default App;
Child1
import React, {useContext} from "react";
import SillyContext from './context'
export default function Child1() {
const sillyContext = useContext(SillyContext)
console.log('[Child 1 ran]')
return (
<div>
<div>[Child 1]: {sillyContext.name}</div>
</div>
)
}
Child2
答案 0 :(得分:1)
更新计数时,Child1会重新渲染的主要问题是因为您每次都将新的对象引用传递给Context Provider。
如果App组件重新渲染,则在其中渲染的所有元素都将重新渲染,除非它们实现了备注或为PureComponent或使用shouldComponentUpdate
您可以进行2项更改来修复您的重新渲染
useMemo
记住作为值传递给提供者的对象App.js
function App() {
const [name, setName] = useState("Radha");
const [count, setCount] = useState(0);
const increaseCount = () => {
setCount(prevState => prevState + 1);
};
const value = useMemo(() => ({ name }), [name]);
return (
<div className="App">
<Child2 count={count} />
<button onClick={increaseCount}>Increase</button>
<input
type="text"
value={name}
onChange={event => setName(event.target.value)}
/>
<SillyContext.Provider value={value}>
<Child1 />
</SillyContext.Provider>
</div>
);
}
Child2
const Child2 = React.memo(function(props) {
console.log("[Child2 Ran!]");
return <div>[Child2] - Count: {props.count}</div>;
});
孩子1
const Child1 = React.memo(function() {
const sillyContext = useContext(SillyContext);
console.log("[Child 1 ran]");
return (
<div>
<div>[Child 1]: {sillyContext.name}</div>
</div>
);
});
答案 1 :(得分:0)
您可以在Child1
组件内使用useMemo。它不能解决重新渲染问题,但可以改进。
Following snippet is third variant proposed by React core dev
我们可以使我们的代码更加冗长,但将其保留在 通过在useMemo中包装返回值并指定单个组件 它的依赖关系。我们的组件仍然可以重新执行,但是React 如果所有useMemo输入都相同,则不会重新渲染子树。
const { useState, useEffect, createContext, useContext, useMemo } = React;
const SillyContext = createContext();
const Child2 = React.memo(({count}) => {
return <div>Count: {count}</div>
})
const Child1 = () => {
const {name} = useContext(SillyContext);
return useMemo(() => {
console.log('Child1');
return <div>
<div>Child 1: {name}</div>
</div>}, [name])
}
const App = () => {
const [count, setCount] = useState(0);
const increaseCount = () => {
setCount(prevState => prevState + 1)
}
return <div>
<Child2 count={count}/>
<button onClick={increaseCount}>Increase</button>
<Child1/>
</div>
}
ReactDOM.render(
<SillyContext.Provider value={{name: 'test'}}>
<App />
</SillyContext.Provider>,
document.getElementById('root')
);
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>