繁体   English   中英

在上下文中调用 React Hook

[英]Calling a React Hook in a Context

我正在使用https://github.com/flatlogic/react-material-admin ,它是一个基于Material UIReact Admin Console ,并带有 react contexthooks设计。

该项目为 User UserContext.js定义了一个 Context ,代码很简单( https://raw.githubusercontent.com/flatlogic/react-material-admin/master/src/context/UserContext.js ):

import React from "react";

var UserStateContext = React.createContext();
var UserDispatchContext = React.createContext();

function userReducer(state, action) {
  switch (action.type) {
    case "LOGIN_SUCCESS":
      return { ...state, isAuthenticated: true };
    case "SIGN_OUT_SUCCESS":
      return { ...state, isAuthenticated: false };
    default: {
      throw new Error(`Unhandled action type: ${action.type}`);
    }
  }
}

function UserProvider({ children }) {
  var [state, dispatch] = React.useReducer(userReducer, {
    isAuthenticated: !!localStorage.getItem("id_token"),
  });

  return (
    <UserStateContext.Provider value={state}>
      <UserDispatchContext.Provider value={dispatch}>
        {children}
      </UserDispatchContext.Provider>
    </UserStateContext.Provider>
  );
}

function useUserState() {
  var context = React.useContext(UserStateContext);
  if (context === undefined) {
    throw new Error("useUserState must be used within a UserProvider");
  }
  return context;
}

function useUserDispatch() {
  var context = React.useContext(UserDispatchContext);
  if (context === undefined) {
    throw new Error("useUserDispatch must be used within a UserProvider");
  }  
  return context;
}

export { UserProvider, useUserState, useUserDispatch, loginUser, signOut };

// ###########################################################

function loginUser(dispatch, login, password, history, setIsLoading, setError) {  

  setError(false);
  setIsLoading(true);

  if (!!login && !!password) {
    setTimeout(() => {
      localStorage.setItem('id_token', 1)
      setError(null)
      setIsLoading(false)
      dispatch({ type: 'LOGIN_SUCCESS' })

      history.push('/app/dashboard')
    }, 2000);
  } else {
    dispatch({ type: "LOGIN_FAILURE" });
    setError(true);
    setIsLoading(false);
  }
}

function signOut(dispatch, history) {
  localStorage.removeItem("id_token");
  dispatch({ type: "SIGN_OUT_SUCCESS" });
  history.push("/login");
}

正如您所看到的loginUser代码是虚拟的,并且没有调用任何 API。 我尝试使用带有钩子的 api fetch 将其连接到服务器。 我使用了swr ( https://github.com/zeit/swr ),这看起来很简单

`....useSWR('/api/login'); ...`

我得到了错误:

React Hook "useSWR" is called in function "loginUser" which is neither a React 

function component or a custom React Hook function  react-hooks/rules-of-hooks

看来我不能把提取放在这里。 但从逻辑上讲,它是它应该出现的地方!

我如何使用swr或这里?!

你需要做这样的事情:

function FetchOnClick() {
  const [shouldFetch, setShouldFetch] = React.useState(false);
  const { data } = useSWR(!shouldFetch ? null : "/api/users/1", fetcher);

  return (
    <>
      <button disable={shouldFetch} onClick={ () => setShouldFetch(true) }>Fetch</button>
      {data ? <h1>{data.fullName}</h1> : null}
    </>
  );
}

受到@sergiodxa 代码的启发: https : //github.com/vercel/swr/issues/254

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM