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<HistoryData[]>([]);
return (
<Context.Provider value={{ history, setHistory }}>
...
</Context.Provider>
)