React.useState 不从 props 重新加载状态
React.useState does not reload state from props
我希望在 props 更改时重新加载状态,但这不起作用并且 user
变量在下一次 useState
调用时没有更新,有什么问题吗?
function Avatar(props) {
const [user, setUser] = React.useState({...props.user});
return user.avatar ?
(<img src={user.avatar}/>)
: (<p>Loading...</p>);
}
根据 ReactJS documentation about Hooks :
But what happens if the friend prop changes while the component is on the screen? Our component would continue displaying the online status of a different friend. This is a bug. We would also cause a memory leak or crash when unmounting since the unsubscribe call would use the wrong friend ID.
你在这里唯一的互动应该发生在道具变化上,这似乎不起作用。您可以(仍然根据文档)使用 componentDidUpdate(prevProps) 主动捕获道具的任何更新。
PS : 我没有足够的代码来判断,但是你不能在你的 Avatar(props) 函数中主动设置 setUser() 吗?
传递给React.useState()
的参数只是该状态的初始值。 React 不会将其识别为 更改 状态,只会设置其默认值。您将希望最初设置默认状态,然后有条件地调用 setUser(newValue)
,这将被识别为新状态,并重新渲染组件。
我建议在没有某种条件的情况下谨慎更新状态,以防止它不断更新,因此每次收到道具时都要重新渲染。您可能需要考虑将状态功能提升到父组件,并将父组件的状态作为道具传递给此 Avatar。
传递给 useState 的参数是初始状态,很像在构造函数中为 class 组件设置状态,不用于在重新渲染时更新状态
如果你想在 prop 改变时更新状态,使用 useEffect
hook
function Avatar(props) {
const [user, setUser] = React.useState({...props.user});
React.useEffect(() => {
setUser(props.user);
}, [props.user])
return user.avatar ?
(<img src={user.avatar}/>)
: (<p>Loading...</p>);
}
我们使用 useState
为变量设置初始值的功能组件,如果我们通过 props 传递初始值,它将始终设置相同的初始值,直到您不使用 useEffect
勾,
例如你的情况这将完成你的工作
React.useEffect(() => {
setUser(props.user);
}, [props.user])
传递给 useEffect 的函数将在渲染提交到屏幕后 运行。
默认情况下,效果 运行 在每次完成渲染后,但您可以选择仅在某些值发生变化时触发它们。
React.useEffect(FunctionYouWantToRunAfterEveryRender)
如果你只传递一个参数给 useEffect 它会在每次渲染后 运行 这个方法
您可以通过将第二个参数传递给 useEffect
来决定何时触发此 FunctionYouWantToRunAfterEveryRender
React.useEffect(FunctionYouWantToRunAfterEveryRender, [props.user])
你注意到我正在传递 [props.user] 现在 useEffect
只会在 props.user
改变时触发这个 FunctionYouWantToRunAfterEveryRender
函数
希望对你的理解有所帮助
让我知道是否需要任何改进谢谢
我创建了这样的自定义挂钩:
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);
您可以为此创建自己的自定义简单挂钩。钩子在更改时更改了默认值。
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);
我希望在 props 更改时重新加载状态,但这不起作用并且 user
变量在下一次 useState
调用时没有更新,有什么问题吗?
function Avatar(props) {
const [user, setUser] = React.useState({...props.user});
return user.avatar ?
(<img src={user.avatar}/>)
: (<p>Loading...</p>);
}
根据 ReactJS documentation about Hooks :
But what happens if the friend prop changes while the component is on the screen? Our component would continue displaying the online status of a different friend. This is a bug. We would also cause a memory leak or crash when unmounting since the unsubscribe call would use the wrong friend ID.
你在这里唯一的互动应该发生在道具变化上,这似乎不起作用。您可以(仍然根据文档)使用 componentDidUpdate(prevProps) 主动捕获道具的任何更新。
PS : 我没有足够的代码来判断,但是你不能在你的 Avatar(props) 函数中主动设置 setUser() 吗?
传递给React.useState()
的参数只是该状态的初始值。 React 不会将其识别为 更改 状态,只会设置其默认值。您将希望最初设置默认状态,然后有条件地调用 setUser(newValue)
,这将被识别为新状态,并重新渲染组件。
我建议在没有某种条件的情况下谨慎更新状态,以防止它不断更新,因此每次收到道具时都要重新渲染。您可能需要考虑将状态功能提升到父组件,并将父组件的状态作为道具传递给此 Avatar。
传递给 useState 的参数是初始状态,很像在构造函数中为 class 组件设置状态,不用于在重新渲染时更新状态
如果你想在 prop 改变时更新状态,使用 useEffect
hook
function Avatar(props) {
const [user, setUser] = React.useState({...props.user});
React.useEffect(() => {
setUser(props.user);
}, [props.user])
return user.avatar ?
(<img src={user.avatar}/>)
: (<p>Loading...</p>);
}
我们使用 useState
为变量设置初始值的功能组件,如果我们通过 props 传递初始值,它将始终设置相同的初始值,直到您不使用 useEffect
勾,
例如你的情况这将完成你的工作
React.useEffect(() => {
setUser(props.user);
}, [props.user])
传递给 useEffect 的函数将在渲染提交到屏幕后 运行。
默认情况下,效果 运行 在每次完成渲染后,但您可以选择仅在某些值发生变化时触发它们。
React.useEffect(FunctionYouWantToRunAfterEveryRender)
如果你只传递一个参数给 useEffect 它会在每次渲染后 运行 这个方法 您可以通过将第二个参数传递给 useEffect
来决定何时触发此FunctionYouWantToRunAfterEveryRender
React.useEffect(FunctionYouWantToRunAfterEveryRender, [props.user])
你注意到我正在传递 [props.user] 现在 useEffect
只会在 props.user
改变时触发这个 FunctionYouWantToRunAfterEveryRender
函数
希望对你的理解有所帮助 让我知道是否需要任何改进谢谢
我创建了这样的自定义挂钩:
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);
您可以为此创建自己的自定义简单挂钩。钩子在更改时更改了默认值。
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);