Home > OS >  Using State to filter the data of a fetch
Using State to filter the data of a fetch

Time:04-15

I'm creating a React native app for a covid form I'm getting the data from a Json so I've used fetch and .then to get the actually json with the question and save it on a QuestionsState, but when I try to filter the data and get the individual question to save that on a QuestionState, that is not showing on the view, but when I console.log that and press ctrl s to save en vs code, the individual question appears

the questions code is this

import { StyleSheet, Text, View, Button } from 'react-native'
import React, {useState, useEffect} from 'react'

const url = 'https://raw.githubusercontent.com/alejoduke52/covidForm/main/covid-19.json'

const Questions = () => {
  

    const [covidQuestions, setCovidQuestions] = useState([{}])
    const [individualQuestion, setIndividualQuestion] = useState([])
    const [loading, setLoading] = useState(true)
    const [countId,setCountId] = useState(1)


    useEffect(() => {

        console.log("cargando use effect")
        
        getData()
        
        
       
      },[])

      useEffect(() => {

        console.log("cargando use effect data unica")
        
        
        getQuestion(1)
       
      },[countId])
      



    const getData = () =>{

      fetch(url)
        .then(resp => resp.json())
        .then(data => {
          setCovidQuestions(data)
          getQuestion(1)
        })

    }

    const getQuestion = (id) => {

      setIndividualQuestion(covidQuestions.filter(Question => Question.id === id))
      console.log(individualQuestion)
      setLoading(false)

    }


    
    const handlerNextQuestion = () => {
      console.log("jasdjasjdas")
      console.log(individualQuestion)
      //getQuestion(countId)
      setCountId(countId 1)

    } 

    




  return (
    <View>
      {
        loading ? <Text style={styles.loading}>LOADING</Text> : (

          <View key={0}>
            <Text>hello {individualQuestion.question}</Text>

          </View>

        )
         
        
        //jsx
      }

      <Button title="Cargando s" onPress={() => handlerNextQuestion()} />
    </View>
  );
}

export default Questions

const styles = StyleSheet.create({


  loading: {

    fontSize: 40

  }
})

It is very strange cause when I first render the app the state is empty but only when I press ctrl s, it shows

CodePudding user response:

individualQuestion state is an array you have to use it like

Option 1:

hello {individualQuestion[0].question}

Option 2:

setIndividualQuestion(covidQuestions.filter(Question => Question.id === id)[0])

CodePudding user response:

You can use getQuestion(1, data) instead of getQuestion(1).

You can pass data to getQuestion function

const getData = () =>{
  fetch(url)
    .then(resp => resp.json())
    .then(data => {
      setCovidQuestions(data)
      getQuestion(1, data)
    })
}

const getQuestion = (id,data) => {
  setIndividualQuestion(data.filter(Question => Question.id === id))
  ...
  ...
  ...
}

CodePudding user response:

Please check the below code It will give you full functionality:

import { StyleSheet, Text, View, Button } from 'react-native'
import React, { useState, useEffect } from 'react'

const url = 'https://raw.githubusercontent.com/alejoduke52/covidForm/main/covid-19.json'

const Questions = () => {
    const [covidQuestions, setCovidQuestions] = useState([])
    const [individualQuestion, setIndividualQuestion] = useState()
    const [loading, setLoading] = useState(true)
    const [countId, setCountId] = useState(1)

    useEffect(() => {
        console.log("cargando use effect")
        getData()
    }, [])

    const getData = () => {
        fetch(url)
            .then(resp => resp.json())
            .then(data => {
                if (data.length > 0) {
                    setCovidQuestions(data)
                    console.log("Data", data)
                    getQuestion(1, data)
                }
            })
    }

    const getQuestion = (id, data) => {
        console.log(data)
        let question = data.find(Question => Question.id === id)
        console.log("Question", question)
        setIndividualQuestion(question)
        setLoading(false)

    }

    const handlerNextQuestion = () => {
        setCountId(countId   1)
        getQuestion(countId   1, covidQuestions)
    }

    return (
        <View>
            {
                loading ? <Text style={styles.loading}>LOADING</Text> : (
                    <View key={0}>
                        <Text>hellO</Text>
                        {individualQuestion != undefined ?
                            <View>
                                <Text>{JSON.stringify(individualQuestion)}</Text>
                                <Text>Question: {individualQuestion.question}</Text>
                            </View> : null}
                    </View>
                )
            }
            <Button title="next" onPress={() => handlerNextQuestion()} />
        </View>
    );
}

export default Questions

const styles = StyleSheet.create({
    loading: {
        fontSize: 40
    }
})

Hope You will like it! :)

CodePudding user response:

Here there are two problem which I see

First problem is you are trying to access covidQuestions immediately after setCovidQuestions inside getQuestion(1) function, since setting state in react is always an asynchronous event and takes some time to update the state value. So basically you should not call getQuestion(1) immediately after setCovidQuestions .

Second, problem I see with the filter you are using, since filter always return an array of filtered questions, even if there is one question, so you can never access individualQuestion like {individualQuestion.question}, since its an array.

My solution to the first problem would be to remove getQuestion(1) after setCovidQuestions inside fetch API call and instead you can actually add covidQuestions as dependency to your useEffect which runs on change of countId like below

JSX

useEffect(() => {
        console.log("cargando use effect data unica")
        getQuestion(1)
      },[countId, covidQuestions])

And for your second problem related to filter mechanism, you can do something like this, while rendering

JSX

<View key={0}>
    <Text>hello {individualQuestion[0].question}</Text>
</View>
  • Related