React Hooks - 返回 useContext 而不破坏 Hooks 规则



我正在调整这段代码,但我无法继续,因为 React 抱怨我的钩子。

// 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,
  });
}

。然后我在登录屏幕中调用它:

// components/LogIn
import React, { useEffect, useState } from 'react';
import { setUser, getUser } from 'components/User/actions';
function click() {
  setUser({
    name: 'John',
    phone: '32323232',
  });
}
function useCurrentUser() {
  const [currentUser, setCurrentUser] = useState(null);
  useEffect(() => {
    setCurrentUser(getUser());
  }, []);
  return currentUser;
}
function Login() {
  const currentUser = useCurrentUser();
  return (
    <div>
      {currentUser && (
        <div>
          <h2>User info</h2>
          <ul>
            <li>Name: {currentUser.name}</li>
            <li>CPF: {currentUser.cpf}</li>
            <li>Phone: {currentUser.phone}</li>
          </ul>
        </div>
      )}
      <button type="button" onClick={click}>
        Set User state
      </button>
    </div>
  );
}
export default Login;

您必须确保在函数组件中使用自定义钩子,并且一个好的约定是用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>

相关内容

  • 没有找到相关文章

最新更新