简体   繁体   English

在上下文中调用 React Hook

[英]Calling a React Hook in a Context

I am using the https://github.com/flatlogic/react-material-admin which is an React Admin Console base on Material UI and design with react context and hooks .我正在使用https://github.com/flatlogic/react-material-admin ,它是一个基于Material UIReact Admin Console ,并带有 react contexthooks设计。

The project defines a Context for User UserContext.js , the code is simple ( https://raw.githubusercontent.com/flatlogic/react-material-admin/master/src/context/UserContext.js ):该项目为 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");
}

As you can see the loginUser code is dummy and is not calling any API.正如您所看到的loginUser代码是虚拟的,并且没有调用任何 API。 I tried to use the api fetch with hook to connect it to a server.我尝试使用带有钩子的 api fetch 将其连接到服务器。 I used swr ( https://github.com/zeit/swr ) which seems easy我使用了swr ( https://github.com/zeit/swr ),这看起来很简单

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

I got the error:我得到了错误:

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

It seems that I can not put the fetch here.看来我不能把提取放在这里。 But logically it is the place where it should be!但从逻辑上讲,它是它应该出现的地方!

How can I use swr or here ?!我如何使用swr或这里?!

You need to do something like this:你需要做这样的事情:

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

Inspired by @sergiodxa's code here: https://github.com/vercel/swr/issues/254受到@sergiodxa 代码的启发: https : //github.com/vercel/swr/issues/254

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

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