[英]Why won't my useEffect() hook fire when updating a react context value?
为什么更新使用 React 上下文的依赖项时我的useEffect
挂钩不会触发? 我将上下文用作向导的一部分,该向导将从用户那里收集大量数据,然后最终在向导的最后一步进行处理。
Person
字段正在更新,在向导的下一页上,我可以检索它们(为简洁起见,我的示例中未显示)。 但是,我想在用户输入姓名和地址后在useEffect
中进行 API 调用以执行一些处理。
这是代码(有点做作):
export interface Person {
name: string;
address: string;
skills: string[]; // collected on a different wizard page
};
const PersonContext = React.createContext(null);
const PersonProvider: React.FC = ({children}) => {
const [personState, setPersonState] = useState<Person>({
name: "",
address: ""
});
return (
<PersonContext.Provider value={personState}>
{children}
</PersonContext.Provider>
);
};
export const PersonPage: React.FC<{}> = () => {
const personState = useContext(PersonContext);
useEffect(() => {
console.log("useEffect");
}, [personState]);
/*
Also tried, but no joy:
useEffect(() => {
console.log("useEffect");
}, [personState.name, personState.address]);
*/
const onNameChanged = (e) => {
if(event.key === "Enter") {
console.log(`name: ${e.target.value}`);
personState.name = e.target.value;
}
};
const onAddressChanged = (e) => {
if(event.key === "Enter") {
console.log(`name: ${e.target.value}`);
personState.address = e.target.value;
}
};
return (
<div>
Name: <input name="name" onKeyDown={(e) => onNameChanged(e)} /> (press enter)
<br />
You typed: <span>{personState.name}</span>
<br/>
<br/>
Address: <input name="address" onKeyDown={(e) => onAddressChanged(e)} /> (press enter)
<br />
You typed: <span>{personState.address}</span>
</div>
);
};
export const App: React.FC<{}> = () => {
return (
<PersonProvider>
<PersonPage />
</PersonProvider>
);
}
我这里还有一个 CodePen 示例:
您正在改变 object。 您应该使用 setState function 来更新它,例如。
代替
const onAddressChanged = (e) => {
if(event.key === "Enter") {
personState.address = e.target.value;
}
};
做这个
const onAddressChanged = (e) => {
if(event.key === "Enter") {
setPersonState(prevState => {...prevState, address: e.target.value)}
}
};
const PersonProvider: React.FC = ({children}) => {
// you should expose both the state object and its setter
const personGetterSetter = useState<Person>({
name: "",
address: ""
});
return (
<PersonContext.Provider value={personGetterSetter}>
{children}
</PersonContext.Provider>
);
};
export const PersonPage: React.FC<{}> = () => {
// unpack them here
const [personState, setPersonState] = useContext(PersonContext);
useEffect(() => {
console.log("useEffect");
}, [personState]);
const onNameChanged = (e) => {
if(event.key === "Enter") {
console.log(`name: ${e.target.value}`);
// Wrong way to go
// do not mutate state object directly
// personState.name = e.target.value;
// use the setter, this is the react way to update state
setPersonState(personState => {
return { ...personState, name: e.target.value }
})
}
};
...
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.