irfan
irfan

Reputation: 102

Javascript | Why it works twice in the beginning

I am using react navigation 5. I want to redirect with Token. But the function works twice and returns null in the first. What is the reason and solution?

export default function Router(){
    const [token, setToken] = useState(null);

    useEffect(() => {
        getToken();
    }, []);

    const getToken = async () => {
        const token = await AsyncStorage.getItem('token');
        setToken(token);
    };

    console.log("token:") //console
    console.log(token)

    return (
        <NavigationContainer>
            <AppStack.Navigator>
                {
                    token=== null ?
                    //..
                }
            </AppStack.Navigator>
        </NavigationContainer>
    );
}
//output
token:
null
token:
eyJhbGci..

Two rounds at the beginning and showing null in the first round prevents the program from running.

Upvotes: 0

Views: 183

Answers (2)

Jordan Enev
Jordan Enev

Reputation: 18664

In your case, the component is rendered 2 times, because of the useEffect hook. It acts as a componentDidMount lifecycle method and updates the state, after the async function is completed, and here the second rerender occurred.

In general, your implementation is good.

However, you can try separating/moving the authentication login (token fetching) in a separate component, something like that:

export default function Auth(props) {
    const [token, setToken] = useState(null);

    useEffect(() => {
        getToken();
    }, []);

    const getToken = async () => {
        const token = await AsyncStorage.getItem('token');
        setToken(token);
    };

    return token ? props.children : '<div>Loading ...</div>' 
}

export default function Router(){
    return (
        <NavigationContainer>
            <AppStack.Navigator>
                // Your Routes definition here ...
            </AppStack.Navigator>
        </NavigationContainer>
    );
}

export default function App() {
  return (
      <Auth>
          <Router />
      </Auth>
  )
}

Upvotes: 1

Rohit Singh
Rohit Singh

Reputation: 80

Setting state is async in react, that's why first time when it is running it gives null because after running everything in the script, it resolve the async call. That's why second time you are getting the token.

See the execution order:

const [token, setToken] = useState(null);
useEffect(() => {         -->(2), after component mounts
  getToken();
 }, []);

 const getToken = async () => {        -->(3)
   const token = await AsyncStorage.getItem('token'); -->(6)
   setToken(token);                    -->(7)
  };

 console.log("token:") //console       -->(4)
 console.log(token)                    -->(5)

 return (                   --> this will execute first (1)
   <NavigationContainer>
     <AppStack.Navigator>
      {
       token=== null ?
                    //..
                }
      </AppStack.Navigator>
    </NavigationContainer>             
  );

Upvotes: 0

Related Questions