您不能在 Next.js 服务器端 (SSR) 中使用 ContextAPI,因为它违反钩子规则。https://reactjs.org/warnings/invalid-hook-call-warning.html
React 将getInitialProps
首先运行,因此最好的解决方案是在那里获取数据并使用 ContextAPI 将其传递给您的组件。
让我们继续看看它的工作方式如下:
创建您的 AppProvider 组件
实现您希望通过 React 组件传递的上下文提供程序功能。
对于这种情况,我们将创建将整个应用程序包装在其中的全局上下文提供程序。
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>
);
}
然后使用这个新的提供程序包装您的应用程序。
<AppProvider>
<App />
</AppProvider>
并进入您的页面,例如index.js
,请尝试以下方式:
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
};
}
根据您的 Next.js 版本,您可能会使用getServerSideProps
代替getInitialProps
,但请注意每个请求都会调用它。
Next.js 将使用 getServerSideProps Data Fetching docs返回的数据在每个请求上预渲染此页面
开始在您的组件上使用 ContextAPI
然后在您的组件中,您可以检查此数据并将其存储到 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>
);
上面的用例并不是最好的用例,但它让我们了解了 Next.js 应用程序中的 ContextAPI 是如何工作的。下面我来解释一下:
您可以在getInitialProps
加载组件之前以 SSR 模式获取数据。
参考