简体   繁体   中英

React authentication with Context API

I've had a problem with authentication using react api context. When I type the login credentials into the form, with the rest api I get an access token, when I get it it sets it to the value "session" in my localStorage and redirect to routes.home which is in my routing array using in Main.tsx to hold private routes. But when i'm redirecting to this home page i'm facing with many nullpointers from Header.tsx cause my account taken from useContext(AppContext) is null. Sometimes i've had also loop over logic in useEffect at App.tsx .

In App.tsx i'm trying to fetch from rest api the whole object of the current user and set to provider.

can someone tell me what i'm doing wrong and how to properly set data to provider an use this data via useContext ?

here is my code:

login/index.tsx

 const onFinish = async (form: any) => {
      try {
        const response = await axios.post("/auth/login", {
            email: form.email,
            password: form.password
        });

        const token = response["token"];
        if (token) {
          localStorage.setItem("session", token);
          history.push(routes.home)
        }
      } catch (error) {
       
      }
  };

Header.tsx

export const Header = () => {
  const { account } = useContext(AppContext);

  return (
    //here is using `account` to display eq. `account.name`
  );
}

Main.tsx

export const Main = ({ account, children }) => {
  return (
    <AppContextProvider account={account}>
       //div's, styles, components, etc.
   </AppContextProvider>

App.tsx

export default function App() {

  const [accountData, setAccountData] = useState(null);
  const history = useHistory();

  useEffect(() => {
    if (localStorage.getItem("session")) {
      const token = localStorage.getItem("session");
      const decode = jwt(token);
  
      const query = {
        id: decode["id"]
      }
  
      const accountResponse: any = async () => {
        const response = await api.get("/auth/account", query);
        setAccountData(response);

        history.push(routes.dashboard);
      }
  
      accountResponse();
    } else {
      history.push(publicRoutes.login);
    }
  })

  return (
    <div className="App">
      <Switch>
        {publicRouting.map(({ path, component }, i) => (
          <Route key={i} path={path} component={component} />
        ))}
        <Main account={accountData}>
          {routing.map(({ path, component }, i) => (
            <Route key={i} path={path} component={component} />
          ))}
        </Main>
      </Switch>
    </div>
  );
}

AppContextProvider.tsx

export const AppContextProvider: FC<AppContextProviderProps> = ({ account, children }) => {
    return (
        <AppContext.Provider
            value={{ 
                account: account
            }}
        >
            { children}
        </AppContext.Provider>
    )
}

thanks for any help!

You can see my code here: https://github.com/muhammadyunusuz/React-Login-Exemple

I created custom hook.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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