这是一个使用 react 钩子的函数式反应组件 - 状态以一种奇怪的方式更新,破坏了我的组件流。关于为什么会发生这种情况以及如何可靠地更新子组件所需的状态的任何想法。目前,我的 firestore 保存不起作用,因为它需要用户 ID,并且由于更新滞后而无法从状态获取它......
const XYZ = (props) => {
const [data, setData] = useState({
...props,
});
const getinitdata = async () => {
let user = await utils.getUser();
console.log("1", user.uid); //USERID
await setData({ ...data, uid: user.uid });
console.log("3", data.uid); //UNDEFINED
}
useEffect(() => {
console.log("componentDidMount");
getinitdata();
console.log("2", data.uid); //UNDEFINED
return () => {
console.log("componentWillUnmount");
};
}, []); // empty-array means don't watch for any updates
console.log("4", data.uid); //USERID
return (
<div>{data.uid}</div>
);
}
上面的控制台.log打印如下:
componentDidMount
2 undefined
1 KMDTFXxktUTwq6Kg34l8r5qWkAL
4 KMDTFXxktUTwq6Kg34l8r5qWkAL
3 undefined
目标只是确保 setData 通过添加一些数据来更新状态,例如此处的 uid。因此,使用状态作为临时存储。
然后,如果函数需要将其作为事务(例如预订(的一部分写入数据库,则此数据应该可用。
我发现与基于类的 this.setState({smth:smth}( 完全不同,我可以依靠它立即更新状态,不能依赖功能函数 - 例如,这不会更新状态 setData({...data, smth:smth}( 使 data.smth 为非空值并准备好发送。
这剥夺了 this.setState 功能,并且不确定使用什么解决方法来让状态在可用后立即存储 var、uid 等......
欢迎就如何做到这一点提出任何想法。
问题仍然是为什么 console.log("3", data.uid(; 是未定义的,尽管在 setData 之前等待。
useEffect
中的箭头函数捕获data
变量,调用setData
不会更新该函数中data
的值,无论您是否使用await
。怎么可能?data
被声明为const
,所以任何看到它的东西都会得到初始值。调用setData
的目的是在下次重新渲染时获取新的值data
。
如果需要可在useEffect
中更改并在之后立即读取的值,请使用const data = useRef
并将data.current
字段更改为所需的值。
附言,你通常不应该复制道具来陈述。
编辑:提供的示例
const XYZ = props => {
const data = useRef(null);
useEffect(() => {
const fn = async () => {
data.current = 1;
await delay(1000);
data.current = 2;
console.log(data.current); // 2
};
fn();
}, []);
return /* whatever */
};
代码有几个问题:
setData
不返回承诺。实际上它不会返回任何内容。所以在上面使用await
没有效果。- 在效果函数中,您正在调用异步函数
getInitialData
但您没有等待它的完成。
假设你想在挂载时获取用户 ID,然后在用户 id 可用后执行一些操作,你可以像这样:
const getInitialData = async () => {
let user = await utils.getUser();
setData({ ...data, uid: user.uid });
}
useEffect(() => {
getInitialData();
}, []);
useEffect(() => {
if(data.uid) {
// whatever needs to be done once uid is available.
}
}, [data.uid]);