skip to Main Content

I’m using this library:

const [userId, setUserId] = useState('');
import AsyncStorage from '@react-native-async-storage/async-storage';

When I Login here, I set the AsyncStorage:

    const storeUserId = async (id) => {
        try {
            await AsyncStorage.setItem(
            'userId',
            id,
            );
        } catch (error) {
            console.log(error);
        }
    }

As so:

   storeUserId(userGuid);
   navigation.navigate("Home");

Then when i navigate to the Home Screen, i have this in useEffect:

     useEffect(() => {

            AsyncStorage.getItem('userId').then(value => {
                if (value != null) {
                    setUserId(value.toString());
                    console.log("u " + value);
                    getData(0);
                }
            });

    }, []);

The console log outputs:

u 52ba85d7-5d16-4012-940d-94cddda978b2

Which is correct, but when getData(0); is called here:

 const getData = async (id) => {
    console.log("2 " + userId);
    setOnRefresh(true);
        fetch('https://soppinga.com/api/Home/GetPolls?id=' + id + "&userId=" + userId, {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json'
            }})
        .then(function(response){
          return response.json();
        })
        .then(function(json){
            heartRef2.current = true;
            heartRef.current = true;
            loadData(json); setOnRefresh(false);
        })
        .catch(function(error) {
        console.log('There has been a problem with your fetch operation: ' + error.message);
         // ADD THIS THROW error
          throw error;
        });
 }

The console log outputs empty userId, so my fetch cannot complete with the userId as empty.

So how do I get the userId in time and be able to pass it in the fetch in time?

2

Answers


  1. Chosen as BEST ANSWER

    I had to separate the useEffect like this:

    useEffect(() => {
    
        AsyncStorage.getItem('userId').then(value => {
            if (value != null) {
                setUserId(value.toString());
                console.log("u " + value);
            }
        });
    
    }, []);
    
    
    
    useEffect(() => {
        if(userId.length > 0){
            getData(0);
        }
    }, [userId]);
    

    So when the setUserId is called, the useEffect containing the getData() will be called for enough time for the userId to be set


  2. Nice to see you solved you problem, while it works for your case you need to be careful that it’s not about "buying time" for the first effect to finish, when you set a state, the new data of the state cannot be accessed in the same render. splitting the effects solved the issue because the second effect will now fire the next time userId changes which is after the next render and it will have access to the new state in its scope

    https://react.dev/reference/react/useEffect

    It you want to use the value of the state directly after setting it, then just use the value itself, and not the state like this:

    useEffect(() => {
    
        AsyncStorage.getItem('userId').then(value => {
            if (value != null) {
                const newUserId = value.toString()
                setUserId(newUserId);
                console.log("userId " + newUserId);
                getData(newUserId) // pass it to the getData function
            }
        });
    
    }, []);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search