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

React中使用Context无法向路由页面组件传递数据求助

问题原因与解决方案

问题原因

  1. Context作用域不覆盖目标组件:你的Context.Provider仅在Overview组件内部,而History是独立的路由页面组件。当从/跳转到/history时,Overview组件会被卸载,History组件不在Provider的包裹层级中,只能读取到Context的默认空数组。
  2. 状态更新存在闭包隐患:handleSubmit中用[...history, clonedValues]更新状态,连续提交时会因闭包捕获旧状态,导致历史记录更新不完整。

解决步骤

1. 重构Context,提升Provider层级

将Context的Provider移到路由组件的外层,确保所有需要访问历史数据的路由组件都在其作用域内。建议单独抽离Context文件,便于维护:

// HistoryContext.tsx
import { createContext, useContext, useState, ReactNode, Dispatch, SetStateAction } from 'react';

export type HistoryData = {
  input: string;
  date: string;
};

type ContextProviderType = {
  history: HistoryData[];
  setHistory: Dispatch<SetStateAction<HistoryData[]>>;
};

export const HistoryContext = createContext<ContextProviderType>({
  history: [],
  setHistory: () => {},
});

export const HistoryProvider = ({ children }: { children: ReactNode }) => {
  const [history, setHistory] = useState<HistoryData[]>([]);
  
  return (
    <HistoryContext.Provider value={{ history, setHistory }}>
      {children}
    </HistoryContext.Provider>
  );
};

export const useHistoryData = () => useContext(HistoryContext);

2. 在App组件中用Provider包裹路由

修改App.tsx,让所有路由组件都能访问Context:

import { Routes, Route } from 'react-router-dom';
import { Overview } from './Overview';
import { History } from './History';
import { HistoryProvider } from './HistoryContext';

function App() {
  return (
    <HistoryProvider>
      <Routes>
        <Route path="/" element={<Overview />} />
        <Route path="/history" element={<History />} />
      </Routes>
    </HistoryProvider>
  );
}

export default App;

3. 修改Overview组件的状态更新逻辑

移除Overview内部的history状态,直接从Context获取setHistory,并改用函数式更新避免闭包问题:

// Overview.tsx
import { useState } from 'react';
import axios from 'axios';
import { useHistoryData } from './HistoryContext';

type Props = {
  children?: React.ReactNode;
};

export const Overview = ({ children }: Props) => {
  const [inputText, setInputText] = useState('');
  const [data, setData] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const { setHistory } = useHistoryData();

  const handleSubmit = (e: React.MouseEvent<HTMLElement>) => {
    e.preventDefault();
    setLoading(false);
    axios
      .get(`https://api.github.com/users/${inputText}/repos`)
      .then((response) => {
        setData(response.data);
      })
      .catch((error) => {
        console.log('error', error);
        setLoading(true);
      });
    
    // 函数式更新获取最新历史状态
    setHistory(prevHistory => [
      ...prevHistory,
      { input: inputText, date: new Date().toLocaleString() }
    ]);
  };

  return (
    // 保留原有的输入框、提交按钮等UI内容
    <div>
      <input 
        type="text" 
        value={inputText} 
        onChange={(e) => setInputText(e.target.value)}
      />
      <button onClick={handleSubmit}>查询</button>
      {/* 其他组件内容 */}
    </div>
  );
};

4. History组件正常读取Context数据

// History.tsx
import { useHistoryData } from './HistoryContext';

const History = () => {
  const { history } = useHistoryData();
  
  return (
    <div>
      <h2>查询历史</h2>
      {history.map((item, index) => (
        <div key={index} style={{ margin: '10px 0', padding: '10px', border: '1px solid #eee' }}>
          <p>输入内容: {item.input}</p>
          <p>操作时间: {item.date}</p>
        </div>
      ))}
    </div>
  );
};

export default History;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:30:48