you cannot use ContextAPI in Next.js server-side (SSR), because it's against hooks rules. https://reactjs.org/warnings/invalid-hook-call-warning.html
React will run getInitialProps
first, so the best solution is to fetch data in there and passing it through your Component using ContextAPI.
Let's go ahead and see it working as below:
Create your AppProvider component
Implement your context provider functions you want to pass through your React components.
For this case, we'll create our global Context provider wrapping the entire application in it.
const AppProvider = ({ children }) => {
const [galleryData, setGalleryData] = React.useState([]);
const handleGalleryData = galleryData => {
setGalleryData(galleryData);
}
const contextProps = {
galleryData,
handleGalleryData
};
return (
<AppContext.Provider value={contextProps}>
{children}
</AppContext.Provider>
);
}
Then wrap your app with this new provider.
<AppProvider>
<App />
</AppProvider>
And into your pages, such as index.js
, try this way:
Index.getInitialProps = async (props) => {
const { req, res, query, ...others } = props;
// use your env variables, endpoint URIs
// ..
... fetch whatever you want..
const galleryProps = await fetch(endpoint); // isomorphic-unfetch
return {
galleryProps,
query,
...others
};
}
Depending on your Next.js version, you might use getServerSideProps
instead of getInitialProps
, but be aware of calling it by each request.
Next.js will pre-render this page on each request using the data returned by getServerSideProps Data Fetching docs
Start using ContextAPI over your components
Then in your components, you can check for this data and store it into ContextAPI
const Index = props => {
const { galleryProps, query, ...others } = props;
const [galleryData, setGalleryData] = useState(galleryProps);
const { handleGalleryData, ...contextRest } = useContext(AppContext);
...
// Here you're going to store data into ContextAPI appropriatly.
useEffect(() => {
if (typeof galleryProps === 'object' && _.keys(galleryProps).length > 0) {
handleGalleryData(galleryProps);
}
}, [handleGalleryData]);
// Other times your page is loaded, you will GET this data from ContextAPI, instead of SSR props.
useEffect(() => {
if (_.keys(galleryDataProps).length <= 0 && _.keys(contextRest.galleryData).length > 0) {
setGalleryData(contextRest.galleryData);
}
}, []);
....
return (
<div>
{JSON.stringify(galleryData)}
</div>
);
The use case above isn't the best one, but it brings an understanding of how things work with ContextAPI in Next.js applications. I'll explain it below:
You may fetch data in SSR mode over getInitialProps
before your component loads.
References
ContextApi
right now. I'm going to post an example. – Sisera