Next.JS -- getInitialProps 通过 ContextProvider 将 props 和 state 传递给子组件

Next.JS -- getInitialProps to pass props and state to child components via ContextProvider

我在 _App.js 中使用 getInitialProps() 来获取一些 api 数据,我想通过 React Context 将该数据作为道具传递给我的其他组件。我想通过构造函数用状态初始化 Context Provider。

首先我通过 createContext().

初始化上下文

config/Context.js:

import { createContext } from 'react';
const Context = createContext();
export default Context;

然后我使用构造函数在其自己的组件中创建 Context.Provider 来初始化状态。

provider/ContextProvider.js:

import React, { Component } from 'react';
import Context from '../config/Context';

class ContextProvider extends Component {
  constructor(props) {
    super(props);
    
    this.state = {
      filters: {
        active: true,
        headerActive: false
      }
    };
  }

  render() {
    return (
      <Context.Provider>
        {this.props.children}
      </Context.Provider>
    );
  }
}

export default ContextProvider;

_app.js 中,我在 getInitialProps() 中进行了一次 API 调用,并将该数据传递给上下文提供程序。

pages/_app.js

import App, { Container } from 'next/app';
import ContextProvider from '../provider/ContextProvider';
import fetch from 'isomorphic-unfetch';

export default class MyApp extends App {
  static async getInitialProps() {
    const res = await fetch('https://node-hnapi.herokuapp.com/news');
    let data = await res.json();

    console.log(data)
    return { articles: data }
  }

  render () {
    const { Component, pageProps } = this.props;
    
    return (
      <Container>
        <ContextProvider value={{ articles: this.props.articles}}>
          <Component {...pageProps} />
        </ContextProvider>
      </Container>
    );
  }
}

此时我假设我可以通过 Context.Consumer 或像 useContext() 这样的钩子访问上下文,但上下文在以下组件中未定义:

components/ArticleList.js:

import React from 'react';
import Context from '../config/Context';

const ArticleList = () => {
  const generateArticles = () => {
    const context = React.useContext(Context);
    console.log(context, 'context') // Context is undefined here
    // return context.articles.map(article => <p>{article.title}</p>)
    // Error: Cannot read property 'articles' because context is undefined
  }

  return (
    <div>
      <h3>Article List</h3>
      {generateArticles()}
    </div>
  );
};

export default ArticleList;

为什么在 components/ArticleList.js 中未定义上下文?我尝试通过 Context.Consumer 将上下文传递到组件中,但我得到了相同的结果。

这是复制问题的回购:https://github.com/joelhoelting/next-context-api-test

ContextProvider.js 中,您忘记将 value 传递给 Context.Provider

import React, { Component } from 'react';
import Context from '../config/Context';

class ContextProvider extends Component {
  constructor(props) {
    super(props);

    this.state = {
      filters: {
        active: true,
        headerActive: false
      }
    };
  }

  render() {
    const { value } = this.props
    return (
      <Context.Provider value={ value }>
        {this.props.children}
      </Context.Provider>
    );
  }
}

export default ContextProvider;