You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React结合Context更新state仅在第二次点击后生效问题求助

问题根源

  • React函数组件的useState返回的状态更新函数不支持第二个回调参数,这是类组件setState的专属特性,你写的setDays(newDays, getNewData())本身是无效写法,而且你直接执行了getNewData()而非传入函数引用。
  • React的状态更新是异步批量处理的,调用setDays后,当前函数作用域内的days变量不会立刻更新,此时直接调用getNewData,传入getData的是更新前的旧days值,所以第一次请求拿到的是旧数据,第二次点击时days已经是上一次更新后的值,才会请求到对应的数据,看起来就需要点击两次才能生效。
  • 函数声明顺序错误:你把getNewData、daysChangeHandler定义在useState声明之前,函数闭包捕获的是初始的days默认值,永远拿不到更新后的状态,这也是你之前加的useEffect不生效的核心原因。

修复方案

直接替换DataContextProvider的代码即可:

import { createContext, useState, useEffect } from 'react'

const DataContext = createContext({ 
  days: 720, 
  data: { timestamp: [], price: [], short_ma: [], long_ma: [], money: [], action: [] }, 
  daysChangeHandler: (newDays) => {} 
})
export default DataContext

export const DataContextProvider = (props) => {
  // 1. 先声明状态,再定义依赖状态的函数,避免闭包捕获旧值
  const [days, setDays] = useState(720)
  const [data, setData] = useState({ timestamp: [], price: [], short_ma: [], long_ma: [], money: [], action: [] })

  // 2. 请求方法接收目标天数作为入参,不依赖当前作用域的状态变量
  const getNewData = async (targetDays) => {
    const response = await getData(targetDays)
    setData(response)
    console.log('NEW DATA')
  }

  const daysChangeHandler = (newDays) => {
    setDays(newDays)
  }

  // 3. 监听days变化,状态更新后自动用最新的天数请求数据
  useEffect(() => {
    getNewData(days)
  }, [days])

  return (
    <DataContext.Provider
      value={{ days, data, daysChangeHandler }}
    >
      {props.children}
    </DataContext.Provider>
  )
}

修改说明

  • 调整了状态和函数的声明顺序,保证函数引用的是最新的状态。
  • 给请求方法加了显式的天数入参,彻底规避闭包旧值问题。
  • 移除了setDays的错误回调写法,改用useEffect监听天数变化自动触发请求,保证每次请求的参数都是最新的。
  • 用async/await优化了异步请求的写法,逻辑更清晰。

内容的提问来源于stack exchange,提问作者Giustino Sulpizio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 14:39:00