关于使用 useContext 和 useReducer 钩子的问题

Question around using useContext and useReducer hooks

我正在尝试练习使用钩子,但我无法绕过它。 我有一个组件 MessageBoard 组件,它从状态中读取数据,它只显示一个简单的消息列表。

我通过 createContext 传递 dispatchstate 以便子组件可以使用它,这又在子组件中使用 useContext读取值。

刷新页面时,我希望看到初始的 UI,但它无法呈现上下文中的值未定义。我在初始化的时候已经给reducer提供了初始状态。

App.js

import React from "react";

import MessageBoard from "./MessageBoard";

import MessagesContext from "../context/MessagesContext";

function App() {
  return (
    <div>
      <MessagesContext>
        <h2>Reaction</h2>
        <hr />
        <MessageBoard />
      </MessagesContext>
    </div>
  );
}

export default App;

MessageBoard.js

import React, { useContext } from "react";

import MessagesContext from "../context/MessagesContext";

function MessageBoard(props) {
  const { state } = useContext(MessagesContext);

  return (
    <div>
      {state.messages.map(message => {
        return (
          <div key={message.id}>
            <h4>{new Date(message.timestamp).toLocaleDateString()}</h4>
            <p>{message.text}</p>
            <hr />
          </div>
        );
      })}
    </div>
  );
}

export default MessageBoard;

MessagesContext.js

import React, { createContext, useReducer } from "react";

import reducer, { initialState } from "../state/reducer";

export default function MessagesContext(props) {
  const Context = createContext(null);
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <Context.Provider
      value={{
        dispatch,
        state
      }}
    >
      {props.children}
    </Context.Provider>
  );
}

错误示例 - https://codesandbox.io/s/black-dust-13kj2

相反,如果我稍微更改 MessagesContext 文件,而不是将 Provider 直接注入到 App,它会按预期工作。想知道我在这里误解了什么以及可能发生了什么?

MessagesContext.js

import { createContext } from "react";

export default createContext(null);

App.js

import React, { useReducer } from "react";

import reducer, { initialState } from "../state/reducer";

import PublishMessage from "./PublishMessage";
import MessageBoard from "./MessageBoard";

import MessagesContext from "../context/MessagesContext";

function App() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <MessagesContext.Provider
        value={{
          dispatch,
          state
        }}
      >
        <h2>Reaction</h2>
        <hr />
        <PublishMessage />
        <hr />
        <MessageBoard />
      </MessagesContext.Provider>
    </div>
  );
}

export default App;

工作示例 - https://codesandbox.io/s/mystifying-meitner-vzhok

useContext 接受上下文对象(从 React.createContext 返回的值)和 returns 该上下文的当前上下文值。

const MyContext = createContext(null);
const value = useContext(MyContext);
// MessagesContext Not a contex object.
const { state } = useContext(MessagesContext);

在第一个例子中:

// export the context.
export const Context = createContext(null);

export default function MessagesContext(props) {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <Context.Provider
      value={{
        dispatch,
        state
      }}
    >
      {props.children}
    </Context.Provider>
  );
}

然后使用它:

import { Context } from '../context/MessagesContext';

function MessageBoard() {
  const { state } = useContext(Context);
...
}

工作失败的例子: