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

React+TypeScript中Context内useState设置后仍为空数组的问题

问题:React Context中useState的setState不生效,state始终为空数组

尝试在React Context结合TypeScript接口管理useState变量,目标是从someArray中获取数据并存入state,但stateData始终输出[],无法更新。

原代码片段

1. 上下文组件代码

import { createContext, useState } from 'react';

export interface exportedInterface {
  stateData: NftsData[];
  fetchUnstakedNFTs: () => void;
}

interface Data {
  dataString: string,
  dataNumber: number,
}

export const customContext = createContext<exportedInterface>();

const CustomContext: FC = ({ children = null as any }) => {
  const [stateData, setStateData] = useState<Data[]>([]);
  let listDataArray: Data[] = [];

  export const fetchSomeArray = async () => {
    for (let item of someArray) {
      await fetch(item.url)
        .then(resp =>
          resp.json()
        ).then((json) => {
          const listData: Data = {  
            {
              dataString: json.stringData,
              dataNumber: json.numberData
            }
          listDataArray.push(listData)
        }
    }
    setStateData(listDataArray) // 此处未生效
  }

  console.log('stateData: ', stateData)

  return (
    <CustomContext.Provider
      value={{
        stateData,
        fetchUnstakedNFTs,
      }}
    >
      {children}
    </CustomContext.Provider>
  );
}

2. 自定义Hook代码

import { useContext } from 'react';
import { CustomContext } from 'aboveFile';

export const useCustomContext = () => {
  const context = useContext(CustomContext);
  if (context === undefined) {
    throw new Error(
      'CustomContext undefined'
    );
  }
  return context;
};

3. 使用组件代码

import { useCustomContext } from 'aboveFile';

export default function App() {
  const { fetchSomeArray } = useCustomContext();
  useEffect(() => { fetchSomeArray() }, [])

  return (
   ...
  )
}

问题现象

执行后控制台始终输出:stateData: [],无论等待多久都无法更新。


错误分析与修复方案

关键问题列表

  1. 函数命名不匹配:Context中定义的异步函数是fetchSomeArray,但Provider的value中传入的是fetchUnstakedNFTs,且接口exportedInterface中声明的也是fetchUnstakedNFTs,导致组件通过useCustomContext获取的fetchSomeArray根本不存在,函数从未被执行。
  2. 语法错误:创建listData对象时多嵌套了一层大括号,导致代码报错,无法执行到setStateData步骤。
  3. 变量作用域问题:listDataArray定义在组件函数内部,每次组件渲染都会被重置为[],存在闭包风险;且异步循环中直接修改数组后setState,不如用函数内临时变量存储结果更安全。
  4. Context初始化缺失默认值:createContext未传入符合exportedInterface的默认值,不符合TypeScript规范。
  5. 组件与Context对象命名冲突:组件名为CustomContext,导出的Context对象名为customContext,容易混淆,建议组件命名为CustomContextProvider。

修复后的完整代码

1. 修复后的上下文组件

import { createContext, useState, FC, ReactNode } from 'react';

// 统一数据类型定义
interface Data {
  dataString: string;
  dataNumber: number;
}

// 修正Context接口,与内部state类型对齐
export interface CustomContextType {
  stateData: Data[];
  fetchSomeArray: () => Promise<void>;
}

// 传入符合类型的默认值
export const CustomContext = createContext<CustomContextType>({
  stateData: [],
  fetchSomeArray: async () => {}
});

// 组件重命名,避免与Context对象冲突
export const CustomContextProvider: FC<{ children: ReactNode }> = ({ children }) => {
  const [stateData, setStateData] = useState<Data[]>([]);

  // 函数命名与接口保持一致
  const fetchSomeArray = async () => {
    // 临时数组在函数内部声明,避免组件渲染重置
    const tempArray: Data[] = [];
    for (const item of someArray) {
      try {
        // 用await替代.then,避免回调嵌套和错误捕获漏洞
        const resp = await fetch(item.url);
        const json = await resp.json();
        // 修正对象语法错误
        const listData: Data = {
          dataString: json.stringData,
          dataNumber: json.numberData
        };
        tempArray.push(listData);
      } catch (err) {
        console.error('Fetch error:', err);
      }
    }
    // 更新state
    setStateData(tempArray);
  };

  // 推荐用useEffect监听state变化,而非组件顶层console.log
  // useEffect(() => {
  //   console.log('stateData updated:', stateData);
  // }, [stateData]);

  return (
    <CustomContext.Provider
      value={{
        stateData,
        fetchSomeArray
      }}
    >
      {children}
    </CustomContext.Provider>
  );
};

2. 修复后的自定义Hook

import { useContext } from 'react';
import { CustomContext } from './path-to-context';

export const useCustomContext = () => {
  const context = useContext(CustomContext);
  if (!context) {
    throw new Error('useCustomContext must be used within a CustomContextProvider');
  }
  return context;
};

3. 修复后的使用组件

import { useEffect } from 'react';
import { useCustomContext } from './path-to-hook';

export default function App() {
  const { fetchSomeArray, stateData } = useCustomContext();

  useEffect(() => {
    fetchSomeArray();
  }, [fetchSomeArray]); // 添加依赖,符合React Hooks规则

  console.log('App stateData:', stateData);

  return (
    <div>
      {/* 渲染stateData内容 */}
      {stateData.map((item, index) => (
        <div key={index}>
          <p>{item.dataString}</p>
          <p>{item.dataNumber}</p>
        </div>
      ))}
    </div>
  );
}

额外说明

  • 组件顶层的console.log会在初始渲染时输出空数组,state更新后会再次渲染并输出新值,若只想看更新后的结果,建议用useEffect监听stateData变化。
  • 异步函数中添加try/catch可捕获请求错误,避免整个循环中断。
  • 确保someArray是已定义的变量,且每个item包含有效的url字段。

内容的提问来源于stack exchange,提问作者cris.sol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 09:40:25