繁体   English   中英

使用 React Context 时没有触发 React 效果挂钩

[英]React effect hook not firing when using React Context

我有一个组件应该创建不同的页面(每个孩子一个)并只显示选定的页面:

import * as React from "react";

export interface SwitchProps {
  pageId: number;
  children: React.ReactChild[];
}

export interface SwitchController {
  setPage: (pageIdx: number) => void;
}

export const SwitchContext = React.createContext<SwitchController>({
  setPage: (pageIdx) => {}
});

const Switch = (props: SwitchProps) => {
  const [pageIdx, setPageIdx] = React.useState(props.pageId);

  const controller: SwitchController = {
    setPage: (pageIdx) => {
      console.log("Changing page idx to", pageIdx);
      setPageIdx(pageIdx);
    }
  };

  React.useEffect(() => {
    console.log("Effect called");
    setPageIdx(props.pageId);
  }, [props.pageId]);

  return (
    <SwitchContext.Provider value={controller}>
      <div>{props.children[pageIdx]}</div>
    </SwitchContext.Provider>
  );
};

export default Switch;

以及使用它的组件:

import * as React from "react";
import "./styles.css";
import Switch, { SwitchContext } from "./Switch";

const Page1 = (props: { value: string }) => {
  const switchContext = React.useContext(SwitchContext);

  const onClick = () => {
    switchContext.setPage(0);
  };

  return (
    <div>
      This is page - {props.value} <button onClick={onClick}>Go to 0</button>
    </div>
  );
};

export default function App() {
  const [pageId, setPageId] = React.useState(0);
  const [value, setValue] = React.useState("The first page");

  const onClick = () => {
    setPageId(0);
  };

  const onClick3 = () => {
    console.log("Attempting to change to 1");
    setPageId(1);
  };

  const onClick2 = () => {
    setValue("I have been changed");
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <div>
        <Switch pageId={pageId}>
          <div>
            <Page1 value={value} />{" "}
            <button onClick={onClick3}>Go to next page</button>
          </div>
          <div>
            <Page1 value="Hello there" />{" "}
            <button onClick={onClick}>back</button>{" "}
            <button onClick={onClick2}>Change it</button>
          </div>
        </Switch>
      </div>
    </div>
  );
}

请注意我如何在组件Switch中创建上下文提供程序,以便默认情况下它所包含的所有组件都能够让 controller 更改页面。


问题

问题如下:

  1. 启动浏览器 => 第 0 页显示
  2. 单击“转到下一页”=>第 1 页显示
  3. 单击“转到 0”=> 第 0 页显示
  4. 再次单击“转到下一页”=> 没有任何反应

我可以看到,从单击“转到 0”按钮的时间开始,当我单击“转到下一页”时, useEffect不再在Switch中触发。

这是为什么?

这不起作用,因为您正在从Page1组件更新上下文 state 值,并且useEffect正在侦听道具更改。 App组件的pageId值保持为 1,因为App组件不知道Page1已将pageId更新为 0。

解决方案是在App组件Go to 0点击事件。

const Page1 = (props: { value: string; onGoToZeroClick: any }) => {
  return (
    <div>
      This is page - {props.value}{" "}
      <button onClick={props.onGoToZeroClick}>Go to 0</button>
    </div>
  );
};  

// App.js
export default function App() {
  const [pageId, setPageId] = React.useState(0);
  const [value, setValue] = React.useState("The first page");

  const onClick = () => {
    setPageId(0);
  };

  const onClick3 = () => {
    console.log("Attempting to change to 1");
    setPageId(1);
  };

  const onClick2 = () => {
    setValue("I have been changed");
  };

  const handleZeroClick = () => {
    setPageId(0);
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <div>
        <Switch pageId={pageId}>
          <div>
            <Page1 value={value} onGoToZeroClick={handleZeroClick} />{" "}
            <button onClick={onClick3}>Go to next page</button>
          </div>
          <div>
            <Page1 value="Hello there" onGoToZeroClick={handleZeroClick} />{" "}
            <button onClick={onClick}>back</button>{" "}
            <button onClick={onClick2}>Change it</button>
          </div>
        </Switch>
      </div>
    </div>
  );
}  

您在两个组件(App 和 Switch)中复制相同的 state 即pageId 您应该重组组件以使用上下文中的 state 变量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM