javascript - useState 本身始终是默认值

标签 javascript reactjs react-hooks

我正在使用useState来管理状态,它工作正常。但是当我在其内部返回状态时,它总是初始值

import react, {useState} from 'react'

const MyComponent = () => {
    const [myState, setMyState] = useState({
        value: 'initial value',
        setValue: (newValue) => {
            setMyState({...myState, value: newValue})
            console.log(myState.value) //<--always is 'initial value'
        }
    })

    return(
        <>
            <p>{myState.value}</p> //<-- it's working fine
            <input value={myState.value} onChange={(e) => myState.setValue(e.target.value)} /> //<--working fine too

        </>
    )
}

我期望console.log是输入值,但实际输出始终是初始值

最佳答案

const [myState, setMyState] = useState({
    value: 'initial value',
    setValue: (newValue) => {
        setMyState({...myState, value: newValue})
        console.log(myState.value) //<--always is 'initial value'
    }
})

第一次运行组件函数时,setValue 函数会捕获 myState初始值。第二次运行时,您将复制 setValue 函数,但该函数已捕获 myState初始值>。它永远不会更新。

由于函数永远不会改变,因此您首先不应将其放入 useState() 中。您可以单独定义该函数。

const [myState, setMyState] = useState({ value: 'initial value' })
const setValue = (newValue) => {
  setMyState({ ...myState, value: newValue })
}

现在,每次运行组件函数时都会创建一个新的 setValue 副本。捕获变量时,可以使用 useCallback()用于优化;如果值没有改变,React 将重用该函数的旧副本。

const [myState, setMyState] = useState({ value: 'initial value' })
const setValue = useCallback((newValue) => {
  setMyState({ ...myState, value: newValue })
}, [myState]) // ← this bit ensures that the value is always up to date inside the callback

正如 Shubham Khatri 提到的,在这种情况下有一个更快更好的方法:使用 functional form of setState .

const [myState, setMyState] = useState({ value: 'initial value' })
const setValue = useCallback((newValue) => {
  setMyState((prev) => ({ ...prev, value: newValue }))
}, []) // ← now we use an empty array, so React will never update this callback

不过,这三种方法中的任何一种都可以使用;对于大多数用例来说,它们都可以工作并表现得足够好。

<小时/>

根据评论,您正在尝试创建一个通过上下文传递的对象。实现此目的的一种方法是在单独的步骤中创建上下文对象,类似于我们创建回调函数的方式。这次,我们使用useMemo ,它类似于 useCallback 但适用于任何类型的对象。

// Per T.J. Crowder's answer, you can use separate `useState` calls if you need multiple values.
const [myState, setMyState] = useState('initial value')
const ctx = useMemo(() => ({
  value: myState,
  setValue: (newValue) => {
    setMyState(newValue)
  }
}), [myState])

return (
  <Provider value={ctx}>
    {children}
  </Provider>
)

关于javascript - useState 本身始终是默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56108962/

相关文章:

javascript - Vue JS - 将默认值注入(inject)自定义单选组

javascript - 有什么方法可以从不同的组件操纵组件的状态?

reactjs - 为什么 react 组件在改变状态后不重新渲染

javascript - React 函数/Hooks 组件上的 componentDidMount 等价物?

javascript - 在 React JS 中更新数组会覆盖旧值

javascript - 单击单独的 div 取消动画状态

javascript - AngularJS 连接所有 js 文件

javascript - Bootstrap 模态力滚动到顶部

reactjs - React Router Transition Animation 缺少超时

reactjs - 如何创建可重用的异步 thunk 而无需不必要的渲染