我期待状态重新加载道具变化,但这并不工作和用户变量没有更新下useState调用,什么是错误的?
function Avatar(props) {
const [user, setUser] = React.useState({...props.user});
return user.avatar ?
(<img src={user.avatar}/>)
: (<p>Loading...</p>);
}
codepen
我期待状态重新加载道具变化,但这并不工作和用户变量没有更新下useState调用,什么是错误的?
function Avatar(props) {
const [user, setUser] = React.useState({...props.user});
return user.avatar ?
(<img src={user.avatar}/>)
: (<p>Loading...</p>);
}
codepen
当前回答
我创建了这样的自定义钩子:
const usePrevious = value => {
const ref = React.useRef();
React.useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
const usePropState = datas => {
const [dataset, setDataset] = useState(datas);
const prevDatas = usePrevious(datas);
const handleChangeDataset = data => setDataset(data);
React.useEffect(() => {
if (!deepEqual(datas, prevDatas)) // deepEqual is my function to compare object/array using deep-equal
setDataset(datas);
}, [datas, prevDatas]);
return [
dataset,
handleChangeDataset
]
}
使用方法:
const [state, setState] = usePropState(props.datas);
其他回答
我们使用useState为变量设置初始值的函数组件,如果我们通过props传递初始值,它将始终设置相同的初始值,直到你不使用useEffect钩子,
比如你的案子这个可以帮到你
React.useEffect(() => {
setUser(props.user);
}, [props.user])
传递给useEffect的函数将在渲染提交到屏幕后运行。
默认情况下,效果在每次渲染完成后运行,但您可以选择仅在某些值发生变化时才触发它们。
React.useEffect(FunctionYouWantToRunAfterEveryRender)
如果你只给useEffect传递一个参数,它会在每次渲染后运行这个方法 你可以通过传递第二个参数给useEffect来决定什么时候触发这个函数youwanttorunaftereveryrender
React.useEffect(FunctionYouWantToRunAfterEveryRender, [props.user])
如你所见,我正在传递[道具。现在useEffect只会在道具时触发这个FunctionYouWantToRunAfterEveryRender函数。修改用户
我希望这能帮助你理解 如果需要任何改进,请告诉我,谢谢
根据ReactJS关于Hooks的文档:
但是如果好友道具在组件出现在屏幕上时发生了变化会发生什么呢?我们的组件将继续显示不同朋友的在线状态。这是一个bug。卸载时还会导致内存泄漏或崩溃,因为取消订阅调用将使用错误的好友ID。
你在这里唯一的互动应该发生在道具的改变上,这似乎不起作用。您可以(仍然根据文档)使用componentDidUpdate(prevProps)来主动捕获对道具的任何更新。
PS:我没有足够的代码来判断,但你不能主动setUser()在你的Avatar(props)函数?
您可以为此创建自己的自定义简单钩子。当默认值改变时,钩子也改变了默认值。
https://gist.github.com/mahmut-gundogdu/193ad830be31807ee4e232a05aeec1d8
import {useEffect, useState} from 'react';
export function useStateWithDep(defaultValue: any) {
const [value, setValue] = useState(defaultValue);
useEffect(() => {
setValue(defaultValue);
}, [defaultValue]);
return [value, setValue];
}
#例子
const [user, setUser] = useStateWithDep(props.user);
传递给React.useState()的参数只是该状态的初始值。React不会将其识别为改变状态,只会设置其默认值。您首先需要设置默认状态,然后有条件地调用setUser(newValue),它将被识别为一个新状态,然后重新呈现组件。
我建议在没有某种条件的情况下谨慎更新状态,以防止它不断更新,因此每次接收道具时都要重新渲染。您可能想考虑将状态功能提升到父组件,并将父组件的状态作为道具传递给这个Avatar。
我创建了这样的自定义钩子:
const usePrevious = value => {
const ref = React.useRef();
React.useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
const usePropState = datas => {
const [dataset, setDataset] = useState(datas);
const prevDatas = usePrevious(datas);
const handleChangeDataset = data => setDataset(data);
React.useEffect(() => {
if (!deepEqual(datas, prevDatas)) // deepEqual is my function to compare object/array using deep-equal
setDataset(datas);
}, [datas, prevDatas]);
return [
dataset,
handleChangeDataset
]
}
使用方法:
const [state, setState] = usePropState(props.datas);