Search code examples
javascriptreactjslocal-storageauth0lifecycle

Why it gets the correct data from localStorage only after refreshing the page in React


I have been unable to deal with this problem in React for a long time and I am asking for your help. I will be very grateful. You going to be my hero? :)) The problem is that I want to assign roles from RoleConnecton to localStorage and then render the components that are suitable for the role. However, this happens only after the page is refreshed. I don't know how to fix this without the need to refresh the page.

App.js ->

const App = () => {
    const { user, isAuthenticated } = useAuth0();
    
      return (
        isAuthenticated && (
        <>
        <RoleConnection />
          <Admin dataProvider={jsonServerProvider('Link to database here')} i18nProvider={i18nProvider}>
    {permissions =>[
      localStorage.getItem("role") ==="medic"
      ?
      <Resource name="employee" list={EmployeeList} edit={EmployeeEdit} create={EmployeeCreate} icon={WorkRounded}/>
      : null,
      <Resource name="hospital" list={HospitalList} edit={HospitalEdit} create={HospitalCreate} icon={LocalHospitalRounded}/>,
      localStorage.getItem("role") === "doctor"
      ? <Resource name="order" list={OrderList} edit={OrderEdit} create={OrderCreate} icon={PersonRounded}/>
      : null,
      localStorage.getItem("role") === "medic"
      ? <Resource name="order" list={OrderList} edit={OrderEditMedic} create={OrderCreateMedic} icon={LocalHospitalRounded}/>
      : null,
      <Resource name="patient" list={PatientList} edit={PatientEdit} create={PatientCreate} icon={PersonRounded}/>,
    ]}
          </Admin>
          <LogoutButton />
          </>
        )
      );
    };
    export default App;

RoleConnection ->

import React from 'react';
import { useAuth0 } from "@auth0/auth0-react";

const RoleConnection = () => {
  const { user, isAuthenticated } = useAuth0();
  const auth_id = 'Auth ID HERE';
  fetch(`Link to Auth0/api/v2/users/${user.sub}/roles`, {
    method: 'get',
    headers: new Headers({
      'Authorization': `Bearer ${auth_id}`
    })
  })
    .then(response => response.json())
    .then(data => {
      let role = data[0].name;
      localStorage.setItem('role', role);


  });

After Editing - Thanks to Someone Special

App.js

const App = () => {
const { user, isAuthenticated } = useAuth0();
const [ role, setRole ] = useState(null)

   useEffect(() => {
     if(user) auth()
  },[user])

  const auth = () => {
    fetch(`Link to Auth0/api/v2/users/${user?.sub}/roles`, {
        method: 'get',
        headers: new Headers({
           'Authorization': `Bearer ${auth_id}`
        })
     })
    .then(response => response.json())
    .then(data => {
      console.log("Data: " + data[0].name)
      setRole(data[0].name)

  });

  
  }
  console.log("Check Role: "+ role);
  return (
    isAuthenticated && (
    <>
    
      <Admin dataProvider={jsonServerProvider('Link to database here')} i18nProvider={i18nProvider}>
{permissions =>[
  console.log("Role "+ role),
  role =="medic"
  ?
  <Resource name="employee" list={EmployeeList} edit={EmployeeEdit} create={EmployeeCreate} icon={WorkRounded}/>
  : null,
  <Resource name="hospital" list={HospitalList} edit={HospitalEdit} create={HospitalCreate} icon={LocalHospitalRounded}/>,
  role === "doctor"
  ? <Resource name="order" list={OrderList} edit={OrderEdit} create={OrderCreate} icon={PersonRounded}/>
  : null,
  role === "medic"
  ? <Resource name="order" list={OrderList} edit={OrderEditMedic} create={OrderCreateMedic} icon={LocalHospitalRounded}/>
  : null,
  <Resource name="patient" list={PatientList} edit={PatientEdit} create={PatientCreate} icon={PersonRounded}/>,
]}
      </Admin>
      <LogoutButton />
      </>
    )
  );
};
export default App;

At this point, there is no error, but the relevant sections are not displayed. From the login console, you can deduce that the null value is entered into the role. However, when I check the data, there is actually a role that should be assigned. Does anyone know how to solve this problem?

enter image description here enter image description here


Solution

  • What you doing is anti pattern. u should move the entire login into App itself.

    App.js

    const App = () => {
    const { user, isAuthenticated } = useAuth0();
    const [ role, setRole ] = useState(null)
    
       useEffect(() => {
         if (user) auth()
      },[user])
    
      const auth = () => {
        fetch(`Link to Auth0/api/v2/users/${user?.sub}/roles`, {
            method: 'get',
            headers: new Headers({
               'Authorization': `Bearer ${auth_id}`
            })
         })
        .then(response => response.json())
        .then(data => {
          setRole(data[0].name)
    
      });
    
      
      }
    
      return (
        isAuthenticated && (
        <>
        
          <Admin dataProvider={jsonServerProvider('Link to database here')} i18nProvider={i18nProvider}>
    {permissions =>[
      role ==="medic"
      ?
      <Resource name="employee" list={EmployeeList} edit={EmployeeEdit} create={EmployeeCreate} icon={WorkRounded}/>
      : null,
      <Resource name="hospital" list={HospitalList} edit={HospitalEdit} create={HospitalCreate} icon={LocalHospitalRounded}/>,
      role === "doctor"
      ? <Resource name="order" list={OrderList} edit={OrderEdit} create={OrderCreate} icon={PersonRounded}/>
      : null,
      role === "medic"
      ? <Resource name="order" list={OrderList} edit={OrderEditMedic} create={OrderCreateMedic} icon={LocalHospitalRounded}/>
      : null,
      <Resource name="patient" list={PatientList} edit={PatientEdit} create={PatientCreate} icon={PersonRounded}/>,
    ]}
          </Admin>
          <LogoutButton />
          </>
        )
      );
    };
    export default App;