使用 ContextAPI 不会重新呈现其使用者,但内容已更改。为什么?
Using ContextAPI doesn't re-render its consumer, but content is changed. Why?
考虑这个小例子。在学习本书的同时,我用 Context API 做了一些实验。
const MyContext = React.createContext(0);
const D3 = () => {
console.log('render D3');
return <MyContext.Consumer>{num => `${num}`}</MyContext.Consumer>;
};
const D2 = React.memo(() => {
console.log('render D2');
return <D3 />;
});
const D1 = React.memo(() => {
console.log('render D1');
return <D2 />;
});
const App = () => {
const [num, setNum] = useState(0);
console.log('render App');
return (
<div>
<MyContext.Provider value={num}>
<D1 />
</MyContext.Provider>
<input type='button' onClick={() => { setNum(Math.random()) }} />
</div>);
};
ReactDOM.render(<App />, document.querySelector('#root'));
当我点击按钮时,我可以看到我的小数字正在变化。另请注意,每次点击都会呈现 App
,而 D1
、D2
则不会。我明白了。
但奇怪的是,当点击按钮时,D3
并没有被重新渲染!它的内容仍然在变化。究竟发生了什么?
为了方便起见,请勾选:https://jsfiddle.net/gfnuko/cs7jpo69/4/
child <MyContext.Consumer>
是 re-rendered。这样做看看:
const D3 = () => {
console.log('render D3');
return <MyContext.Consumer>{num => {console.log('CONSUMER'}; return num;}}</MyContext.Consumer>;
};
考虑这个小例子。在学习本书的同时,我用 Context API 做了一些实验。
const MyContext = React.createContext(0);
const D3 = () => {
console.log('render D3');
return <MyContext.Consumer>{num => `${num}`}</MyContext.Consumer>;
};
const D2 = React.memo(() => {
console.log('render D2');
return <D3 />;
});
const D1 = React.memo(() => {
console.log('render D1');
return <D2 />;
});
const App = () => {
const [num, setNum] = useState(0);
console.log('render App');
return (
<div>
<MyContext.Provider value={num}>
<D1 />
</MyContext.Provider>
<input type='button' onClick={() => { setNum(Math.random()) }} />
</div>);
};
ReactDOM.render(<App />, document.querySelector('#root'));
当我点击按钮时,我可以看到我的小数字正在变化。另请注意,每次点击都会呈现 App
,而 D1
、D2
则不会。我明白了。
但奇怪的是,当点击按钮时,D3
并没有被重新渲染!它的内容仍然在变化。究竟发生了什么?
为了方便起见,请勾选:https://jsfiddle.net/gfnuko/cs7jpo69/4/
child <MyContext.Consumer>
是 re-rendered。这样做看看:
const D3 = () => {
console.log('render D3');
return <MyContext.Consumer>{num => {console.log('CONSUMER'}; return num;}}</MyContext.Consumer>;
};