React Hooks-在不违反Hooks规则的情况下返回useContext

时间:2019-04-11 14:03:22

标签: reactjs react-hooks

我正在调整此代码,但由于React在抱怨我的钩子而无法前进。

id6

当我尝试使用// globalStateManager.js import React, { createContext, useContext, useReducer } from 'react'; import PropTypes from 'prop-types'; export const StateContext = createContext(); export const StateProvider = ({ reducer, initialState, children, }) => ( <StateContext.Provider value={useReducer(reducer, initialState)}> {children} </StateContext.Provider> ); export const getState = () => useContext(StateContext); 函数时,会引发以下错误:

getState

如何在遵守这些规则的同时访问上述上下文?

编辑

我在创建用于检索登录用户的操作中使用Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See <link> for tips about how to debug and fix this problem. 函数,例如:

getState

...然后将其称为“登录”屏幕:

// shared/User/actions.js
import { getState } from 'shared/utils/globalStateManager';
import { SET_USER, GET_USER } from './types';

export function setUser(payload) {
  const [state, dispatch] = getState();
  dispatch({
    type: SET_USER,
    payload,
  });
}

export function getUser() {
  const [state, dispatch] = getState();
  dispatch({
    type: GET_USER,
  });
}

1 个答案:

答案 0 :(得分:2)

您必须确保在功能组件中使用自定义钩子,良好的惯例是使用use前缀命名自定义钩子,例如useStateContext

const { createContext, useContext, useReducer, Fragment } = React;

const StateContext = createContext();

const StateProvider = ({ reducer, initialState, children }) => (
  <StateContext.Provider value={useReducer(reducer, initialState)}>
    {children}
  </StateContext.Provider>
);

const useStateContext = () => useContext(StateContext);

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function App() {
  const [state, dispatch] = useStateContext();

  return (
    <Fragment>
      Count: {state.count}
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
    </Fragment>
  );
}

ReactDOM.render(
  <StateProvider reducer={reducer} initialState={initialState}>
    <App />
  </StateProvider>,
  document.getElementById("root")
);
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>