Home > Net >  Cannot pass data to child component with Context React
Cannot pass data to child component with Context React

Time:09-20

I am storing some data in my parent component to an array of objects. After that I am storing it in Context in order to pass it to another component. So my parent looks like this:

    export type HistoryData = {
          input: string;
          date: string;
        };
        
        type Props = {
          children?: ReactNode;
        };
        
        type ContextProviderType = {
          history: HistoryData[];
          setHistory: React.Dispatch<React.SetStateAction<HistoryData[]>>;
        };
        
        const values = {} as HistoryData;
        
        export const Context = createContext<ContextProviderType>({
          history: [],
          setHistory: () => {},
        });
        
        export const Overview = ({ children }: Props) => {
          const [inputText, setInputText] = useState('');
          const [data, setData] = useState<any[]>([]);
          const [loading, setLoading] = useState(false);
          const [history, setHistory] = useState<HistoryData[]>([]);
        
          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);
              });
            const clonedValues = { ...values };
            clonedValues.input = inputText;
            clonedValues.date = new Date().toLocaleString();
            setHistory([...history, clonedValues]);
          };
          console.log(history);
      <Context.Provider value={{ history, setHistory }}>
    ....
</Context.Provider>
     );
    };
    
    export const useContextData = () => useContext(Context);

So basically, after each input i am storing the input and the exact date of the input while it clicked, and later i want to pass it to the other component like that:

import { useContextData } from './Overview';

    const History = () => {
      const { history, setHistory } = useContextData();
      console.log(history);

but all I get is an empty history array [].

Just to clarify, the History component is another page with /history url... I am not sure maybe that re-renders and clears the array??

My App.tsx:

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

export default App;

And my index.tsx:

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

Any help would be appreciated! :)

CodePudding user response:

In order to share a context, two components must be descendents of the same Provider. That means that you need to have the context provider as a parent to your components.

Export Context and useContextData into another file.

In your App.tsx file you will need to wrap the routes in the context provider:

function App() {
  const [history, setHistory] = useState<HistoryData[]>([]);
  return (
    <Context.Provider value={{ history, setHistory }}>
      <Routes>
        <Route path="/" element={<Overview />} />
        <Route path="/history" element={<History />} />
      </Routes>
    </Context.Provider>
  );
}

Then in each of the files you would access the history and setHistory props using context:

   const History = () => {
      const { history, setHistory } = useContextData();
   export const Overview = ({ children }: Props) => {
      const { history, setHistory } = useContextData();

This should solve the issue.

CodePudding user response:

You are using useContext hook inside the History component. But you have created the context inside the Overview component. You must pass the values to Overview component in order to use it in History component.

const [history, setHistory] = useState&lt;HistoryData[]&gt;([]);

        return (
            &lt;Context.Provider value={{ history, setHistory }}&gt;
            ...
            &lt;/Context.Provider&gt;
        )
  • Related