I’m fetching data with react-query
and using Context API
to make the fetched data available to other components:
kitsDataContext.js
import { useQuery } from '@tanstack/react-query'
import axios from 'axios'
import { createContext } from 'react';
export const kitsDataContext = createContext();
//creates provider so content on the database can be accessible to all components
export const kitsDataProvider = ({children}) => {
const fetchKits = async () => {
const response = await axios.get("https://localhost:5001/kitsDB");
return response.data;
};
//saves JSON data on "data" variable
function RQKitsDB(){
const { isLoading, data } = useQuery("kitsDB", fetchKits);
return { isLoading, data };
};
return(
<kitsDataContext.Provider value={{RQKitsDB}}>
{children}
</kitsDataContext.Provider>
);
};
export default kitsDataProvider;
In another file I consumed that data on a component, I also wrapped that component on the same file to make it ready to render on my index.js
:
SerumRow.js
import "./row.css"
import {Button} from 'react-bootstrap';
import AddToCart from './AddToCart.js';
import { useContext } from 'react';
import { kitsDataContext } from './contexts/kitsDataContext.js'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { kitsDataProvider } from './contexts/kitsDataContext.js'
const queryClient = new QueryClient()
//complete row with all the data from database, also adds AddToCart button below every kit
function SerumRowNoProviders() {
//consume context
const { RQKitsDB } = useContext(kitsDataContext);
const { isLoading, data } = RQKitsDB();
return (
<div className="small-container">
<h1>SERUM PRESETS</h1>
<div className="row">
<div className="col-3 text-center">
<img src="./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg" alt="Product 1" />
<div>{data.aa[0].name}</div>
<div className="priceReact"></div>
<AddToCart />
</div>
<div className="col-3 text-center">
<img src="./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg" alt="Product 2" />
<div>{data.aa[1].name}</div>
<div className="priceReact"></div>
<AddToCart />
</div>
<div className="col-3 text-center">
<img src="./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg" alt="Product 3" />
<div>{data.aa[2].name}</div>
<div className="priceReact"></div>
<AddToCart />
</div>
<div className="col-3 text-center">
<img src="./images/WavSupply-Sidepce-Elysium-Loop-Kit-920x920.jpg" alt="Product 4" />
<div>{data.aa[3].name}</div>
<div className="priceReact"></div>
<AddToCart />
</div>
</div>
{/*takes user to page with all available kits */}
<h1><button type="button" id="show-more" className="btn btn-outline-dark btn-lg">BROWSE ALL</button></h1>
</div>
);
}
//wraps SerumRowNoProviders() with needed Providers
function SerumRow() {
return (
<QueryClientProvider client={queryClient}>
<kitsDataProvider>
<SerumRowNoProviders />
</kitsDataProvider>
</QueryClientProvider>
);
}
export default SerumRow;
Finally, I render it on the HTML:
index.js
const serumRow = document.getElementById("SerumRow");
root = ReactDOM.createRoot(serumRow);
root.render(
<React.StrictMode>
<SerumRow />
</React.StrictMode>
);
The problem is that I am getting an error regarding useContext():
react__WEBPACK_IMPORTED_MODULE_2__.useContext(...) is undefined
SerumRowNoProviders@http://localhost:3000/main.b08a434d0e7255432ca0.hot-update.js:44:56
renderWithHooks@http://localhost:3000/static/js/bundle.js:22007:31
mountIndeterminateComponent@http://localhost:3000/static/js/bundle.js:25293:17
beginWork@http://localhost:3000/static/js/bundle.js:26589:20
callCallback@http://localhost:3000/static/js/bundle.js:11599:18
invokeGuardedCallbackDev@http://localhost:3000/static/js/bundle.js:11643:20
invokeGuardedCallback@http://localhost:3000/static/js/bundle.js:11700:35
beginWork$1@http://localhost:3000/static/js/bundle.js:31574:32
performUnitOfWork@http://localhost:3000/static/js/bundle.js:30821:16
workLoopSync@http://localhost:3000/static/js/bundle.js:30744:26
renderRootSync@http://localhost:3000/static/js/bundle.js:30717:11
performSyncWorkOnRoot@http://localhost:3000/static/js/bundle.js:30409:38
flushSyncCallbacks@http://localhost:3000/static/js/bundle.js:18439:26
flushSync@http://localhost:3000/static/js/bundle.js:30513:11
scheduleRoot@http://localhost:3000/static/js/bundle.js:31880:18
./node_modules/react-refresh/cjs/react-refresh-runtime.development.js/performReactRefresh/<@http://localhost:3000/static/js/bundle.js:33918:21
performReactRefresh@http://localhost:3000/static/js/bundle.js:33903:29
./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js/createDebounceUpdate/enqueueUpdate/refreshTimeout<@http://localhost:3000/static/js/bundle.js:807:17
Removing the useContext()
call allows it to compile correctly, so it’s clear that the error relates to that. I thought the cause was axios.get()
not fetching the data quick enough (as it is an async function) so as you can see I used the await
operator but that didn’t help.
2
Answers
you can try to move the context provider to wrap
SerumRow.js
component insideindex.js
insideReact.StrictMode
wrapperThis was tricky.
The issue is that
kitsDataProvider
is not a component because of the the first letterk
is not capitalK
(they are almost the same 😂)If you fix the import
The context will be provided to
SerumRowNoProviders
.