React - useState 未设置初始值

rub*_*bie 19 reactjs react-hooks

我正在重构以使用 Hooks,但遇到了一个非常令人困惑的问题

我有一个基本的功能组件,如下所示:

export const MakeComponent = props => {
  const { path, value, info, update } = props;

  const [val, setVal] = useState(value);
  console.log(value, val); // abc undefined

 return (...)
}
Run Code Online (Sandbox Code Playgroud)

日志返回abc undefined- 即value在 props 中明确定义,但从返回的第一个参数useState(value)undefined

只是为了测试钩子是否正常工作,我尝试useState("abc")并按abc预期记录。

我不知道我做错了什么 - 有什么想法吗?

反应版本: 16.8.6

编辑这里是父组件 - 就我所见,这里没有什么花哨的!

<MakeComponent
  path={key}
  value={item[key]}
  info={value}
  update={updateDiffs}
/>
Run Code Online (Sandbox Code Playgroud)

Pur*_*ret 33

正如评论中提到的那样,useState(initialState)(或任何你称之为的)只会initialState在第一次渲染时使用。

初始渲染期间,返回的状态 ( state) 与作为第一个参数 ( initialState)传递的值相同。

React Docs,重点是我的)

在此之后,在重新渲染时 useState 函数不会根据传入的 props 的新更改来更改状态。

要在每次更改时反映value更改,请在输入道具上注册一个效果,如下所示

export const MakeComponent = props => {
  const { path, value, info, update } = props;

  const [val, setVal] = useState(value);
  useEffect(() => { setVal(value)}, [value] )

 return (...)
}
Run Code Online (Sandbox Code Playgroud)


Sel*_*çuk 7

当您将 prop 传递value给它时useState,它的值可能尚未设置。value本身可能还没有undefined

也不setState是真正同步,因此如果使用与您的状态useState相同的机制,可能尚未设置为初始值。setStatevalvalue

在这种情况下,使用 props 作为状态的初始值,您应该使用没有依赖性的副作用。一旦实现第一个渲染,效果将运行并使用 prop 设置您的状态。您可以让组件的初始值未定义,不传递任何内容,没有任何问题。

export const MakeComponent = props => {
  const { path, value, info, update } = props;

  const [val, setVal] = useState();

  // get initial state after initial render
  useEffect(() => {
    setVal(value)
  }, [])
  console.log(value, val); // abc undefined then will log abc abc

 return (...)
}
Run Code Online (Sandbox Code Playgroud)

请记住,React 中的 props 是只读的,state 是用于读写的。但如果您使用 prop 作为状态的初始值,并使用您在之后通过 prop 设置的状态而不是 prop,那么这完全没问题,而且不是反模式。这是为了保持一致性,因为在特定情况下,您可能会同时从 prop 和 state 获得两个不同的值。

您的案例可能需要在任意时间关心道具的价值,具体取决于您的需求,如上述答案之一所强调的那样。你的问题没有说明这一点。不过,如果是这样,您可以将道具添加到效果的依赖数组中,以使用该道具设置状态,并且可以为您想要相同效果的其他道具编写单独的效果。

如果您不需要编写该数据,则根本不需要该模式,只需使用 prop 即可,它将是最新的,并且您将具有一致性。但你显然是这样做的,我希望我上面建议的模式对你有用,就像对我一样。


Rid*_*tel 6

在这里,您必须添加useEffect是否要在道具更改时更新状态,它将监听道具更改并相应地更新状态值

这是更新的片段

export const MakeComponent = props => {
     const { path, value, info, update } = props;
        
     const [val, setVal] = useState(value);
     useEffect(() => { setVal(value)}, [value] )
     return (<div>{val}</div>)
}
Run Code Online (Sandbox Code Playgroud)

附加沙箱链接

https://codesandbox.io/s/confident-agnesi-ohkq7?file=/src/MakeComponent.js