在下面的代码段中,当传递上下文的值时,useCallback 会阻止所有按钮按预期重新渲染。即clickFunction
缓存。
Stackblitz:https ://stackblitz.com/edit/react-wnfesi
clickFunctionContext.js
import { GlobalContext } from "./GlobalState";
export const ClickFuncContext = createContext();
export const ClickFuncProvider = ({ children }) => {
const { speakerList, setSpeakerList } = useContext(GlobalContext);
const clickFunction = useCallback(speakerIdClicked => {
setSpeakerList(currentState => {
return currentState.map(rec => {
if (rec.id === speakerIdClicked) {
return { ...rec, favorite: !rec.favorite };
}
return rec;
});
});
}, []);
return (
<ClickFuncContext.Provider value={clickFunction}>
{children}
</ClickFuncContext.Provider>
);
};
也就是说,当我从下面的文件中引用这个上下文时,只有我点击的按钮被渲染,而不是其他按钮。
演讲者.js
import React, { useContext } from "react";
import { ClickFuncContext } from "./clickFunctionContext";
export default React.memo(({ speaker, clickFunction }) => {
console.log(`speaker ${speaker.id} ${speaker.name} ${speaker.favorite}`);
const clickFunction = useContext(ClickFuncContext)
return (
<>
<button
onClick={() => {
clickFunction(speaker.id);
}}
>
{speaker.name} {speaker.id}{" "}
{speaker.favorite === true ? "true" : "false"}
</button>
</>
);
});
但是,我需要的是将 useContext 中的 clickFunction 作为属性而不是值返回。
所以,我需要改变这一行:
const clickFunction = useContext(ClickFuncContext)
到:
const { clickFunction } = useContext(ClickFuncContext)
而且,在clickFunctionContext.js
我改变这一行:
<ClickFuncContext.Provider value={{clickFunction}}>
到:
<ClickFuncContext.Provider value={clickFunction}>
该应用程序可以工作,但所有按钮都重新呈现,就好像我没有完成回调一样。
感谢理解为什么这与没有额外参考的情况不同。
这是损坏的 stackblitz:https ://stackblitz.com/edit/react-b6jrt8
这是 stackblitz 中的解决方案,如下所述。https://stackblitz.com/edit/react-pdglx5