我正在使用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/