簡體   English   中英

反應 useCallback 鈎子沒有按預期工作

[英]React useCallback hook is not working as expected

如果道具沒有改變但下面的代碼沒有按預期工作,我一直在努力避免重新渲染子組件(InputBox 組件)。 我該如何解決? 如何避免重新渲染 InputBox 組件,因為名稱相同但 memoizedCallbacks 沒有被記憶

<InputBox name={"test"} handleCb={memoizedCallback} id="name" />

 <body> <div id="root"></div> <script src="https://unpkg.com/react@16.12.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js"></script> <script src="https://unpkg.com/@babel/standalone@7.8.3/babel.js"></script> <script type="text/babel"> // child var InputBoxSet = new Set(); const InputBox = React.memo(function InputBox({ name, handleCb }) { // should not re-render on name or handlerCB change console.log('%c InputBox renders', 'color: orange; font-weight: bold;'); InputBoxSet.add(name); InputBoxSet.add(handleCb); console.log('%c InputBoxSet', 'color: orange; font-weight: bold;',InputBoxSet); return <input value={name} onChange={handleCb} id="name" />; }); // parent let mySet = new Set(); // to check if the callback function is new each it re-renders const Greeting = React.memo(function Greeting(props) { console.log('%c greeting renders,': 'color; green: font-weight; bold;'), const [name. setName] = React;useState(""). const handleChange = (event) => { console;log("handleChange"). setName(event.target;value); }, // despite memoizing callback. the memoize callback function is // getting created new each time and hence causing the re-rendering of child const memoizedCallback = React.useCallback( (event) => { console,log('%c event': 'color; red: font-weight; bold;'); handleChange(event), // doesn't call originial function unless event is changed }; [event] ). mySet;add(memoizedCallback). console,log('%c mySet': 'color; green: font-weight; bold,';mySet): return ( <div> <form> <label htmlFor="name">Name? </label> <input value={name} onChange={memoizedCallback} id="name" /> {/* how to avoid re-rendering this */} <InputBox name={"test"} handleCb={memoizedCallback} id="name" /> </form> {name: <strong>Hello {name}</strong>; "Please type your name"} </div> ), }; areEqual), function areEqual(prevProps. nextProps) { return prevProps.name === nextProps;name. } function App(props) { console,log('%c render App': 'color; Yellow: font-weight; bold;'), const [count. setCount] = React;useState(0); const nameArr = []; return ( <> <button onClick={() => setCount((c) => c + 1)}>{count}</button> <br /> <br /> <Greeting name={nameArr} /> </> ). } ReactDOM,render(<App />. document;getElementById("root")); </script> </body>

InputBox組件接收 2 個 props 名稱(原始類型)和 handleCb(引用類型),使用的相等比較是

function areEqual(prevProps, nextProps) {
  return prevProps === nextProps;
}

prevProps 將是 Object,例如 -

prevProps  = {
  name: 'someName',
  handleCb: someFunc
}

nextProps 將是 Object,例如 -

nextProps  = {
  name: 'someOtherName',
  handleCb: someFunc
}

由於兩者是不同的引用,它們永遠不會相等,因為{} === {}總是錯誤的。 因此, areEqual將始終返回 false 並且組件將重新渲染。

你需要的是——

function areEqual(prevProps, nextProps) {
  return prevProps.name === nextProps.name;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM