Javascript 如何将函数传递到自己的react上下文提供程序中,以便您编辑状态?

Javascript 如何将函数传递到自己的react上下文提供程序中,以便您编辑状态?,javascript,reactjs,react-hooks,react-context,react-state,Javascript,Reactjs,React Hooks,React Context,React State,我有以下代码: import React,{useState}来自“React” export const NumberContext=React.createContext() 导出函数NumberProvider({children}){ 常量[numbers,setNumbers]=useState([]) 函数addNumber(number){ 常量副本=[…数字] 复制。推送(数字) 设置编号(副本) } 返回( {儿童} ) } 导出函数App(){ 返回( ) } 导出函数d

我有以下代码:

import React,{useState}来自“React”
export const NumberContext=React.createContext()
导出函数NumberProvider({children}){
常量[numbers,setNumbers]=useState([])
函数addNumber(number){
常量副本=[…数字]
复制。推送(数字)
设置编号(副本)
}
返回(
{儿童}
)
}
导出函数App(){
返回(
)
}
导出函数displayNumber(){
常量[numbers,addNumbers]=useContext(NumberContext)
返回({numbers}

) }
如果我现在通过提供程序中的上下文api调用
addNumber()
函数,如下所示

导出函数AlterNumbers(){
常量[numbers,addNumber]=useContext(NumberContext)
函数号(){
地址编号(1)
设置超时(()=>{
地址号码(2)
}, 3000)
}
返回()
}
数字
等于
[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>;
};
如注释中所述,您应该使用
useffect
将逻辑更改为更健壮的逻辑:

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>
  )
}
将函数导出到提供程序({children}){
const[toasts,setToasts]=useState([])
const[key,setKey]=useState(0)
函数showToast(标签、消息){
设置键(键+1)
敬酒([
…干杯,
{
钥匙
标签,
消息
},
])
}
useffect(()=>{
设置超时(()=>{
const copy=[…干杯]
copy.pop()
setToasts(副本)
}, 5000)
},敬酒);
返回(
{儿童}
)
}

将整个代码而不是片段放入组件函数体中。
addNumber
调用是否在组件函数体中?是的,确切地说,它们在组件函数体中,而组件函数体位于自定义数字提供者组件内请更新您的问题,显示整个代码,预期的行为是什么,为什么在函数体中?是否要计算渲染的数量?详细说明。使用functional
useState
,并尝试解释您想做得更好的地方,如果没有更多信息,很难提出建议。我真正想要实现的是在我的应用程序中为Toast(通知消息)创建一个消息队列。祝酒者应该被推到队列中,并在一段时间后被移走。我想通过上下文api从代码中的任何地方推送它们。在另一个地方,我想映射队列并显示当前在此队列中的所有消息。这是我的实际代码库:,我的主要问题是,我的自定义上下文提供程序中的useState似乎没有正确更新。您应该使用带有
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>
  )
}