我有以下代码:
import React, { useState } from 'react'
export const NumberContext = React.createContext()
export function NumberProvider({ children }) {
const [numbers, setNumbers] = useState([])
function addNumber(number) {
const copy = [...numbers]
copy.push(number)
setNumbers(copy)
}
return (
<NumberContext.Provider value={[numbers, addNumber]}>
{children}
</NumberContext.Provider>
)
}
export function App() {
return (
<NumberProvider>
<DisplayNumbers />
<AlterNumbers />
</NumberProvider>
)
}
export function DisplayNumbers() {
const [numbers, addNumbers] = useContext(NumberContext)
return (<p>{numbers}</p>)
}
如果我现在通过提供程序中的 Context api 调用 addNumber()
函数,如下所示
export function AlterNumbers() {
const [numbers, addNumber] = useContext(NumberContext)
function alterNumbers(){
addNumber(1)
setTimeout(() => {
addNumber(2)
}, 3000)
}
return (<button onClick={alterNumbers}>)
}
numbers
等于 [2]
而不是 [1, 2]
我的提供程序函数 NumberProvider
中的状态不会像 NumberContext.Provider
中的状态那样更新。我怎样才能防止这种情况发生?实现这一点的设计模式会是什么样子?
最佳答案
由于 useState
的 setter 是异步的,因此一个调用会覆盖另一个调用:
const NumberConsumer = () => {
const [numbers, addNumber] = useContext(NumberContext);
addNumber(1); // Will update numbers to [1] in "future"
setTimeout(() => { // Will update numbers to [2] in "future"
addNumber(2); // The call within the timeout,
// is not aware of the previous state
}, 3000);
return <h1>{JSON.stringify(numbers)}</h1>;
};
您应该使用functional useState
:
setState(prevState => {
// Object.assign would also work
return {...prevState, ...updatedValues};
});
正如评论中所讨论的,您应该使用 useEffect
将逻辑更改为更健壮的内容:
export function ToastProvider({ children }) {
const [toasts, setToasts] = useState([])
const [key, setKey] = useState(0)
function showToast(label, message) {
setKey(key + 1)
setToasts([
...toasts,
{
key,
label,
message,
},
])
}
useEffect(() => {
setTimeout(() => {
const copy = [...toasts]
copy.pop()
setToasts(copy)
}, 5000)
}, toasts);
return (
<ToastContext.Provider value={[toasts, showToast]}>
{children}
</ToastContext.Provider>
)
}
关于javascript - 如何将函数传递到自己的 react 上下文提供程序中以允许您编辑状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57841179/