skip to Main Content
import { View, Text, StyleSheet, Pressable, Button, ActivityIndicator, Alert, FlatList } from 'react-native';
import { useEffect, useState } from 'react';
import { supabase } from '../lib/supabase';
import { useAuth } from '../providers/AuthProvider';
import { Quizz } from '../types/db'
import { Stack } from 'expo-router';

export default function dailyQuizz() {
    const [listeQuestion, setListeQuestion] = useState<Quizz[]>([]);
    const { user } = useAuth();
    const [selected, setSelected] = useState('');
    const [score, setScore] = useState(0);
    const [questionEnCours, setQuestionEnCours] = useState<Quizz>();

    
    const fetchQuizz = async () => {
        console.log('Fetching....');
            
        let { data, error } = await supabase.from('questions').select('*').limit(3).returns<Quizz[]>();


        if (error) {
            Alert.alert('Error fetching data');
            console.log(error);
        }
        if(data){
            setListeQuestion(data);           
        }

    };
    useEffect(() => {
        fetchQuizz();
        setQuestionEnCours(listeQuestion[0]) ;
        console.log(listeQuestion);
    },[])

   /*const shuffleList:quizzFunction = (array) => {
       console.log('preshuffle  ' + array)
       array.sort(() => Math.random() - 0.5);
       console.log('shuffle' + array)
   }


   const shuffle = (array: []) => {
       array.sort(() => Math.random() - 0.5);
       console.log('shuffle' + array)
       return array;
   }*/


    return (
        <View>
            <Stack.Screen options={{ title: questionEnCours?.question }} />
            <Text> { questionEnCours?.question }</Text>
            {/*< FlatList
                data={questionEnCours?.reponses}
                renderItem={({ item }) => (
                    <Pressable onPress={() => setSelected(item)} key={item} style={styles.optionContainer}>
                        <Text>{item}</Text>
                    </Pressable>

                )} /> */}

        </View>

    );
}

Hello everyone !

I’am trying to build a program that can display some questions in a mobile device.
My useEffect is giving some random results:
when i use this code:

useEffect(() => {
        fetchQuizz();
        setQuestionEnCours(listeQuestion[0]) ;
        console.log(listeQuestion);
    },[])

it always display me an empty array

when i use this code:

useEffect(() => {
        fetchQuizz();
        setQuestionEnCours(listeQuestion[0]) ;
        console.log(listeQuestion);
    })

it gives me an infinite loop with the correct data

When i use this one

useEffect(() => {
        fetchQuizz();
        setQuestionEnCours(listeQuestion[0]) ;
        console.log(listeQuestion);
    },[questionEncours])

It gives me sometimes the correct data, sometimes an empty array without any changes from me.

During the tutorial here i already had the same issue with random answers given by my useEffect.

I might be doing something wrong here with the useEffect but the fact that sometimes i got random answer make me think that maybe my environment or something else can be the problem.

I’am new with ReactNativ so it can be a very trivial fix
My english is not that good so let me know if you don’t understand me

I have tried multiple things, the more relevant are the ones above

3

Answers


  1. Chosen as BEST ANSWER

    Thank you it is working for now !

    Just to be clear, my first attempt wasn't working because i was using ListeQuestion[0] wich was not updated in the current state right ?

    Have you any explanation for the fact that i had random answers? Is it possible that while i was updating my code the program kept in memory the ListeQuestion i fetched with my infinite loop for example ?


  2. Let’s first talk about useEffect. Essentially, it performs a simple job: it takes a function and a dependency array, and operates as follows:

    1. Without a second parameter (dependency array): The function (first parameter) is fired on every render of the component (such as when state changes or the parent component rerenders).
    2. With an empty dependency array: The function is called only on the first render.
    3. With a dependency array containing items: The function is called on the first render and whenever any dependency changes.

    Now, regarding your code, here are two approaches:

    1-Setting both states after a successful API call:

    const fetchQuizz = async () => {
        console.log('Fetching....');
        
        let { data, error } = await supabase.from('questions').select('*').limit(3).returns<Quizz[]>();
    
        if (error) {
            Alert.alert('Error fetching data');
            console.log(error);
        } else if (data) {
            setListeQuestion(data);    
            setQuestionEnCours(data[0]);
        }
    };
    
    useEffect(() => {
        fetchQuizz();
    }, []);
    

    2-Setting state in a second useEffect to ensure the data is fetched before setting the second state:

    useEffect(() => {
        // Called once on mount
        fetchQuizz();
    }, []);
    
    useEffect(() => {
        if (listeQuestion.length === 0) return;
        setQuestionEnCours(listeQuestion[0]);
        console.log(listeQuestion);
    }, [listeQuestion]);
    
    Login or Signup to reply.
  3. A problem might be that your fetchQuizz function is async and inside the useEffect hook you are not awaiting it, which you should do if you are using async functions (or you could also use a Promise).

    useEffect(async () => {
        await fetchQuizz();
        setQuestionEnCours(listeQuestion[0]) ;
        console.log(listeQuestion);
    },[])
    

    This will make sure, that the rest of the functions are called, after the fetch function is done. This might fix the behaviour of "sometimes its correct, sometimes its not". Furthermore I would move the setQuestionEnCours call, inside the fetchQuizz function, then maybe you wont even need to make the useEffect hook async.

    One thing I want to say about the useEffect dependancy array (the array at the end of the useEffect hook.

    If the array is empty, the useEffect hook will only be called then the component mounts.
    If the array is containing a variable for example, the useEffect will always be triggered if the value of the variable is changing.
    To not use a dependancy array inside a useEffect hook, is bad practice as far as I am concerned. Hope this helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search