[英]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 更改页面。
问题如下:
我可以看到,从单击“转到 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.