Home > Software engineering >  React Context not passing data on first render
React Context not passing data on first render

Time:01-06

I'm have a problem with Context in React, in this context i load user data (like id, name, role etc) and in website it's work fine, problems starts on fetchToken function where i find firebase token and send it to backend:

const [userData, setUserData] = useState<any>([]);
const [isTokenFound, setTokenFound] = useState<boolean>(false);

      const [userLoading, setUserLoading] = useState<any>(true);
      useEffect(() => {
        if (isAuth)
          apiClient
            .get("api/v1/user/params")
            .then(({ data }) => {
              setUserData(data);
              setUserLoading(false);
              fetchToken({
                setTokenFound,
                userData,
                userLoading,
              });
            })

Here is fetchToken function where i have problem with userData:

export const fetchToken = ({setTokenFound, userData, userLoading}:FirebaseProps) => {

    return getToken(messaging, { vapidKey: 'fake' }).then((currentToken) => {
        if (currentToken) {
      console.log("current token for client: ", currentToken);
      setTokenFound(true);
      console.log("firebase", userData);

      // Track the token -> client mapping, by sending to backend server
      // show on the UI that permission is secured
      if (
        userData.data.notification_token_needs_to_update ===
        true
      )
        apiClient
          .post(
            `api/v1/user/${userData.data.id}/create-notification`,
            {
              push_notification_token: currentToken,
            }
          )
          .then((response) => {
            if (response.status === 204) {
              console.log("token send to backend", {
                push_notification_token: currentToken,
                user_browser: browserAndOS,
              });
            }
          })
          .catch((error) => {
            if (error.response && error.response.status === 422) {
            } else {
              console.error(error);
            }
          });
    } else {
      console.log(
        "No registration token available. Request permission to generate one."
      );
      setTokenFound(false);
      // shows on the UI that permission is required
    }
    }).catch((err) => {
        console.log('An error occurred while retrieving token. ', err);
        // catch error while creating client token
    });
}

It's doesn't seems like FCM problem, I'm just don't have context userData on first render and i don't understand why

There is console.log on first render: enter image description here

And there is after i change some code in IDE and save it: enter image description here

It's really annoying problem, i'm even tried save data to localStorage first, but it's undefined even then, looks like i don't see some fundamental thing here...

CodePudding user response:

setState is asynchronous. Not 100% sure if it will help.

const [userData, setUserData] = useState<any>([]);
const [isTokenFound, setTokenFound] = useState<boolean>(false);

const [userLoading, setUserLoading] = useState<any>(true);

useEffect(() => {
    if (isAuth)
      apiClient
        .get("api/v1/user/params")
        .then(({ data }) => {
          setUserData(data); // asynchronous
          setUserLoading(false); // asynchronous
          fetchToken({
            setTokenFound,
            userData, // <- state has not been updated yet, you passing old state value []
            userLoading, // <- same, you passing true
          });
        })

Just pass what you recieve from response.

const [userLoading, setUserLoading] = useState<any>(true);
  useEffect(() => {
    if (isAuth)
      apiClient
        .get("api/v1/user/params")
        .then(({ data }) => {
          setUserData(data);
          setUserLoading(false);
          fetchToken({
            setTokenFound,
            data,
            false,
          });
        }, []) // Add empty dependency array, so this effect only runs on first render
  • Related