Reactjs 避免在更新上下文时运行效果挂钩

Reactjs 避免在更新上下文时运行效果挂钩,reactjs,react-hooks,Reactjs,React Hooks,我有一个组件MyContainer,它有一个状态变量(通过useStatehook定义),定义了一个上下文提供程序,它将状态变量作为值传递给该提供程序,还包含两个子组件MySetCtxComponent和MyViewCtxComponent MySetCtxComponent可以更改存储在调用set函数的上下文中的值,该函数也作为上下文的一部分传递,但不会呈现它 相反,MyViewCtxComponent会呈现存储在上下文中的值 MySetCtxComponent还通过useffecthook定

我有一个组件
MyContainer
,它有一个状态变量(通过
useState
hook定义),定义了一个上下文提供程序,它将状态变量作为值传递给该提供程序,还包含两个子组件
MySetCtxComponent
MyViewCtxComponent

MySetCtxComponent
可以更改存储在调用set函数的上下文中的值,该函数也作为上下文的一部分传递,但不会呈现它

相反,MyViewCtxComponent会呈现存储在上下文中的值

MySetCtxComponent
还通过
useffect
hook定义了一个效果。例如,此效果用于以固定的时间间隔更新上下文的值

这三个组件的代码是

MyContainer

export function MyContainer() {
  const [myContextValue, setMyContextValue] = useState<string>(null);

  const setCtxVal = (newVal: string) => {
    setMyContextValue(newVal);
  };

  return (
    <MyContext.Provider
      value={{ value: myContextValue, setMyContextValue: setCtxVal }}
    >
      <MySetCtxComponent />
      <MyViewCtxComponent />
    </MyContext.Provider>
  );
}
导出函数MyContainer(){
const[myContextValue,setMyContextValue]=useState(null);
常量setCtxVal=(newVal:string)=>{
setMyContextValue(newVal);
};
返回(
);
}
MySetCtxComponent (加上一个全局变量,使示例更简单)

let计数器=0;
导出函数MySetCtxComponent(){
const myCtx=useContext(MyContext);
useffect(()=>{
console.log(“=======>>>>>>>>>>>>在MySetCtxComponent中运行的使用效果”);
const intervalID=setInterval(()=>{
myCtx.setMyContextValue(“新值”+计数器);
计数器++;
}, 3000);
return()=>clearInterval(intervalID);
},[myCtx]);
返回(计数器=0)}>重置;
}
MyViewCtxComponent

export function MyViewCtxComponent() {
  const myCtx = useContext(MyContext);

  return (
    <div>
      This is the value of the contex: {myCtx.value}
    </div>
  );
}
导出函数MyViewCtxComponent(){
const myCtx=useContext(MyContext);
返回(
这是contex的值:{myCtx.value}
);
}
现在我的问题是,每次更新上下文时,
MySetCtxComponent
的效果都会再次运行,即使这根本不是必需的,因为更新上下文时不需要渲染
MySetCtxComponent
。但是,如果我从
useffect
钩子的依赖项数组中删除
myCtx
(这会在上下文更新时阻止效果钩子),那么我会得到一个es lint警告,例如
React钩子useffect缺少依赖项:“myCtx”。包括它或删除依赖项数组react hooks/deps

最后一个问题是:在这种情况下,忽略警告是安全的,还是我有一个基本的设计错误,可能应该选择使用商店?认为这个例子看起来很愚蠢,但是它是真实场景中最简化的版本。
要复制案例

解决此问题的一种模式是将上下文一分为二,为操作提供一个上下文,为访问上下文值提供另一个上下文。这允许您正确地实现useEffect的预期依赖关系数组,同时也不会在只有上下文值更改时不必要地运行它

const{useState,createContext,useContext,useffect,useRef}=React;
const ViewContext=createContext();
const ActionsContext=createContext();
函数MyContainer(){
const[contextState,setContextState]=useState();
返回(
)
}
函数MySetCtxComponent(){
const setContextState=useContext(ActionsContext);
常量计数器=useRef(0);
useffect(()=>{
console.log(“=======>>>>>>>>>>>>在MySetCtxComponent中运行的使用效果”);
const intervalID=setInterval(()=>{
setContextState(“新值”+计数器当前值);
计数器.current++;
}, 1000);
return()=>clearInterval(intervalID);
},[setContextState]);
返回(counter.current=0)}>Reset;
}
函数MyViewCtxComponent(){
const contextState=useContext(ViewContext);
返回(
这是上下文的值:{contextState}
);
}
ReactDOM.render(
,
document.getElementById(“根”)
);

您通常会使用
export function MyViewCtxComponent() {
  const myCtx = useContext(MyContext);

  return (
    <div>
      This is the value of the contex: {myCtx.value}
    </div>
  );
}