Problem with setState in React Native/ Expo

41 Views Asked by At

I'm learning React Native with Expo and I encountered this problem where setState doesn't update the state when i pass a value. I'm trying to make a function that play audio and save its control to a state whenever i press on a button:

import React, { useState} from "react";
import { Audio } from "expo-av";
const [soundObj, setSoundObj] = useState(null);
const [soundStatus, SetSoundStatus] = useState(null);
const handleAudioPress = async (audio) => {
        try {
            console.log(soundStatus); // always null (initial value)
            if (!soundStatus) {
                const sound = new Audio.Sound();
                const sanitizedUri = audio.uri
                    .replace(/#/g, "%23")
                    .replace(/\?/g, "%3F")
                    .replace(/ /g, "%20");
                const stt = await sound.loadAsync(
                    { uri: sanitizedUri },
                    { shouldPlay: true }
                );

                console.log(sound) //always show the right value
                console.log(stt) //always show the right value

                setSoundObj(sound); //doesn't work???
                SetSoundStatus(stt); //doesn't work???
            }
            if (soundStatus && soundStatus.isLoaded && soundStatus.isPlaying) {
                console.log('sound is playing');
            }
        } catch (e) {
            console.log(e);
        }
    };

I passed this function through props:

const renderItem = ({ item }) => {
        return (
            <AudioListItem
                title={item.filename}
                duration={item.duration}
                onAudioPress={() => handleAudioPress(item)}
                onOptionPress={() => {
                    currentItem.current = item;
                    setModalVisibility((v) => !v);
                }}
            />
        );
    };

Here is where it is used:

export default function AudioListItem({ title, duration, onOptionPress,onAudioPress }) {
    return (
        <>
            <View style={styles.container}>
                <TouchableWithoutFeedback onPress={onAudioPress}>
                    <View style={styles.left}>
                        //...irrevelant code

I put console.log right above the setState and it always showed the right value. I've tried making a deep copy of the values that i need and pass to the setState - doesn't work; pass an interger - still doesn't work. I had basic knowledge about React but i don't know if there are differents in useState of React and React Native, please give me some insight about the problem.

1

There are 1 best solutions below

0
bagi2info.com On

useState is working, but the problem is, it's not update the value in real time if you try to access the state after updating, it will not work, you need to use useEffect to watch the value and decide the flow.

this will not work..

                console.log(sound) //always show the right value
                console.log(stt) //always show the right value

                setSoundObj(sound); //doesn't work???
                SetSoundStatus(stt); //doesn't work???
            }

            if (soundStatus && soundStatus.isLoaded && soundStatus.isPlaying) {
                console.log('sound is playing');
            }

this will work..

const handleAudioPress = async (audio) => {
        try {
            console.log(soundStatus); // always null (initial value)
            if (!soundStatus) {
                const sound = new Audio.Sound();
                const sanitizedUri = audio.uri
                    .replace(/#/g, "%23")
                    .replace(/\?/g, "%3F")
                    .replace(/ /g, "%20");
                const stt = await sound.loadAsync(
                    { uri: sanitizedUri },
                    { shouldPlay: true }
                );

                console.log(sound) //always show the right value
                console.log(stt) //always show the right value

                setSoundObj(sound); //doesn't work???
                SetSoundStatus(stt); //doesn't work???
            }
        } catch (e) {
            console.log(e);
        }
    };

useEffect(() => {
            if (soundStatus && soundStatus.isLoaded && soundStatus.isPlaying) {
                console.log('sound is playing');
            }
}, [soundStatus])