Home > Net >  Correct Way to Update Sate before Async call
Correct Way to Update Sate before Async call

Time:12-22

I am trying to update state to show an ActivityIndicator while an asynchronous call is being made.

What is the correct way of doing this to ensure IsLoading(true) and setResult(null) will happen before the the async call?

In the code below setIsLoading is not actually updated before the async call and thus the ActivityIndicator does not appear on the UI. I realize why this is the case (here) I just don't know the recommended way to do actually ensure the ActivityIndicator shows before the async call is made.

Please help. What is the correct way to do this in react?

const MyScreen = () => {
    const [isLoading, setIsLoading] = useState(false);
    const [result, setResult] = useState(null);

    const handlePress = async () => {

        setResult(null);  // reset result
        setIsLoading(true);  // show activity indicator

        const result = await MyAsyncFunc();  // native modules function
        setResult(result);
        setIsLoading(false);  // turn off activity indicator

    }

    return (
        <View style={styles.container}>
            <MyButton title="Run" handlePress={handlePress} disabled={isLoading} />
            {isLoading && <ActivityIndicator size="large" color="#00ff00" />}
            <Text>{result}</Text>
        </View>
    )
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center'
    },
})

CodePudding user response:

Can you try using just one state? no need isLoading for this I think. try this

{!result && <ActivityIndicator size="large" color="#00ff00" />}

EDIT: lets utilize useEffect to listen to if isLoading is true

...
useEffect(() => {
 async function load (){
  if (isLoading) {
   const result = await MyAsyncFunc();  // native modules function
   setResult(result);
   setIsLoading(false);  // turn off activity indicator
  }
 }
 load()
}, [isLoading])

const handlePress = () => {
   setResult(null);  // reset result
   setIsLoading(true);  // show activity indicator
}

CodePudding user response:

Try adding useEffect and set isLoading false on changing of result dependency there, like this:

const MyScreen = () => {
    const [isLoading, setIsLoading] = useState(false);
    const [result, setResult] = useState(null);

    const handlePress = async () => {

        setResult(null);  // reset result
        setIsLoading(true);  // show activity indicator

        const result = await MyAsyncFunc();  // native modules function
        setResult(result);
        //setIsLoading(false);  // turn off activity indicator

    }

    useEffect(() => {
        if(result && isLoading){
            setIsLoading(false);
        }
    }, [isLoading, result])

    return (
        <View style={styles.container}>
            <MyButton title="Run" handlePress={handlePress} disabled={isLoading} />
            {isLoading && <ActivityIndicator size="large" color="#00ff00" />}
            <Text>{result}</Text>
        </View>
    )
}

Hope this works for you

  • Related