Home > Net >  In React, what is the proper way to await looking up a value in sessionStorage?
In React, what is the proper way to await looking up a value in sessionStorage?

Time:01-02

I'm using React 16. I have a hook where I determine if a session token has been stored in session storage ...

import { useEffect } from 'react';
import { useAuthenticationState, useAuthenticationDispatch } from '../context';

const useAuthentication = () => {
  const authenticationState = useAuthenticationState();
  const updateAuthenticationState = useAuthenticationDispatch();

  useEffect(() => {
    const auth_token = sessionStorage.getItem('token');
    console.log("auth token: "   auth_token);
    updateAuthenticationState({
      type: 'field',
      fieldName: 'isAuthenticated',
      payload: !!auth_token,
    });
  }, [updateAuthenticationState]);

  const isAuthenticated = authenticationState.isAuthenticated;

  return {
    isAuthenticated,
  };
};

export default useAuthentication;

I would like to pass the value of what is stored in session storage to a component that will either render another component or redirect based on the value of the my hook ...

const DirectoryApp = () => {
  console.log("starting get hook value ...");
  const { isAuthenticated } = useAuthentication();
  console.log("is auth:"   isAuthenticated);

  return (
      <Router>
        ...
                  <PrivateRoute
                  authed={isAuthenticated} path="/unapproved-list/"
                  component={UnapprovedList}
                  />

But this line

const { isAuthenticated } = useAuthentication();

isn't properly getting the value of what is in sessionStorage -- it is always initialy returning false. I think this is because I'm not awaiting the result of what the hook returns, but if I do this

const { isAuthenticated } = await useAuthentication();  

I get the error

Syntax error: Unexpected reserved word 'await'. (24:31)

How do I properly await the value of what the hook returns?

CodePudding user response:

Effect is being called after the initial render of the DirectoryApp component. It means your useAuthentication hooks gets whatever is stored in the authenticationState and returns it without any dependency on the code inside of the useEffect hook at that point ant returns the the DirectoryApp component, DirectoryApp renders with this initial value and only after that the effect is being executed.

There's nothing to await as there's no async code in the code you provided.

Based on your imports and code structure I assume you are trying to use React.Context with reducer inside to manage authentication state. In this case you have your AuthenticationProvider component of some sort sowhere wrapping the DirectoryApp so you can solve the issue there by moving the session storage read to the reducer's third initializer parameter:

const reducer = (state, action) => {
    // reducer logic
};

const StateContext = createContext();
const DispatchContext = createContext();
const useAuthenticationState = () => useContext(StateContext);
const useAuthenticationDispatch = () => useContext(DispatchContext);

const AuthenticationProvider = ({ children }) => {
    const [state, dispatch] = useReducer(reducer, { isAuthenticated: false }, (arg) => {
        const auth_token = sessionStorage.getItem('token');
        
        return { ...arg, isAuthenticated: !!auth_token };
    });
    
    return (
        <DispatchContext.Provider value={dispatch}>
            <StateContext.Provider value={state}>
                {children}
            </StateContext.Provider>
        </DispatchContext.Provider>
    );
};

const App = () => (
    <AuthenticationProvider>
      <DirectoryApp />
    </AuthenticationProvider>
);

sessionStorage.getItem is a synchronous function so you will get properly initialized state before the first render of the DirectoryApp.

  • Related