5

我正在用 NextJS 构建一个应用程序。我的应用程序显示一个帖子列表,用户可以从 AZ 或 ZA 对列表进行排序,并在每页显示特定数量的帖子(10、20 等)。当用户单击帖子以访问该特定帖子页面然后返回主列表时,排序和分页首选项被重置,我设法使用 cookie 保留保留的值,但我想useContext()改用。对于这个应用程序,我有一个Layout.js文件,并认为这将是插入我Provider这样的正确位置:

import React, {useState} from 'react';
import Navbar from './Navbar';
import Head from 'next/head';
import {SortingContext} from './UseContext';

const Layout = (props)=> {
  const [value, setValue] = useState('hello');

  return (<SortingContext.Provider value={{value, setValue}}>
            <div>
                <Head>
                  <title>MyApp</title>
                </Head>
                <Navbar/>
                {props.children}
            </div>
            </SortingContext.Provider>
        )};

但是当我尝试从我的一个页面中获取价值时,我得到了TypeError: Cannot read property 'value' of null

useContext在我的应用程序的其他地方使用,所以我知道我可以让它工作。我只是不明白将它放在我的 NextJS 应用程序的哪个位置,因此即使我访问不同的页面,该值也会持续存在。

这是我试图打印值的 index.js:

import React, { useState, useEffect, useContext } from 'react';
import withData from '../lib/apollo';
import Layout from '../components/Layout';
import {SortingContext} from '../components/UseContext';
import Footer from '../components/Footer';

const Home = () => {

  const {value, setValue} = useContext(SortingContext);

  return (
    <Layout>
      <div className='main_screen'>
  <h1>{value}</h1>
      </div>
      {siteOptions && <Footer />}
    </Layout>
  )
};

export default withData(Home);

还有我的 UseContext.js:

import {createContext} from 'react';

export const SortingContext = createContext(null);

4

2 回答 2

5

问题是您试图useContext在提供上下文的树中更高。现在,您的提供者在 中Layout,但是,您正在尝试使用它,Home它是布局的父级。所以你可以做几件事,你可以将你的提供者移到更高的位置Home,或者如果你想保持你当前的结构,你可以做以下事情:

const Home = () => {

  const {value, setValue} = useContext(SortingContext);

  return (
    <Layout>
      <SortingContext.Consumer>
         {value =>
            <div className='main_screen'>
              <h1>{value}</h1>
            </div>
            {siteOptions && <Footer />}
         }
      </SortingContext.Consumer>
    </Layout>
  )
};

但是,我的建议可能是将其提高,您可以在应用程序级别使用它。

于 2020-06-09T18:35:28.010 回答
0

如果您想在整个项目中使用 Context 相同的商店或 Redux,我希望这个建议可以帮助您:

理念:您必须在项目中创建对象以保存您的分页和/或您的标签,如果用户单击一个帖子并发送回文章,您必须在您的商店中使用您的分页,并且当您刷新页面时此商店可以重置请做同样的事情这个:

在 _app.js 中项目根目录的 Provider 顶部创建,或者您可以在文章组件的顶部创建它

<ConfigProvider>
   <your project/>
</ConfigProvider>

在您的项目的 src 中,您可以在目录提供程序上创建并导入此文档中的所有内容,现在创建您的商店,如下所示:

import { createContext, useContext } from "react";
import React, { useState } from "react";
export const ConfigContext = createContext();
export const ConfigDispatcherContext = createContext();

function ConfigProvider({ children }) {
       const [config, setConfig] = useState({
          type: null,
          page: 1,
          tab: null,
          selectTab: null,
          Filter: {
              sort: "desc",
              type: null,
          },
   });
    return (
    <ConfigContext.Provider value={config}>
        <ConfigDispatcherContext.Provider value={setConfig}>
            {children}
        </ConfigDispatcherContext.Provider>
    </ConfigContext.Provider>
 );
}
function useConfigState() {
   return useContext(ConfigContext);
}
function useConfigSetState() {
  return useContext(ConfigDispatcherContext);
}
export { useConfigState, useConfigSetState };
export default ConfigProvider;

最重要的是,您可以在对象上使用相同的商店,这意味着 config 和 setConfig 如果您只想要页面,您可以仅在页面参数上使用 config 变量,现在如何在您的项目中使用它,请参见下文:首先从您在巡回演出中的导演与此相同:

import {
ConfigDispatcherContext,
ConfigContext,
} from "../../providers/ConfigProvider";

现在你在你的函数组件中使用了同样的这个:

    const setConfig = React.useContext(ConfigDispatcherContext);
    const config = React.useContext(ConfigContext);

现在您可以使用控制台看到您的商店,如下所示:

console.log(config)

以及如何在商店中设置分页,您可以使用 setConfig 简单地设置商店,如下所示:

但请注意,如果您的项目更新您的状态,您必须使用正确的 useEffect

   useEffect(()=> {
      setConfig({
         type: "your type",
         page: your pagination number,
         tab: "your custom tab if you want",
          etc...
       })
    },[your pagination change])

从文章返回后,您可以在组件中使用正确的 useEffect 加载相同的页面

const [currentPage, setCurrentPage] = useState(1);
useEffect(()=>{
    setCorrentPage(config.page)
 },[])

我希望这个建议可以帮助你并且有用。祝你好运!

于 2021-09-29T13:38:25.967 回答