Home > Blockchain >  React State is Changing Without Using setState()
React State is Changing Without Using setState()

Time:12-26

I'm developing a quiz/test website. I want to see different questions when I move to next question and don't want to see same answers at the same time.

  • I have a state array varaible which is calling allWords. This state will keep all words.
  • And I have another state array variable which calls like neverAskedWords. This state will keep words which never used always.

I'm creating a new array variable and defining with allWords in a function. When I'm removing any record in the new array variable then that record is removing in allWords variable as well... Why?

I want to remove any record in that temporary array and want to save updated version to neverAskedWords state. In this way I could see different questions always. Here is my codes.

const [allWords, setAllWords] = useState([])
const [neverAskedWords, setNeverAskedWords] = useState([])

async function getAllData(){
    
    axios
    .get(`http://127.0.0.1:3000/api/improve-language`)
    .then(res => {
      setAllWords(res.data)//defining allWords
      setNeverAskedWords(res.data)//defining neverAskedWords
      firstQuestionAndAnswers(res.data)//sending all datas by parameter, bacause when I'm trying to get datas by using `allWords` state, it would be undefined. That's why sending all data by parameter for the first time to set first question and answers.
    })
    .catch(err =>{
      console.log(err)
    })

  }

async function firstQuestionAndAnswers(wordsList){

    let neverAskedList = await wordsList //creating and defining temporary variables
    const allWordsList = await wordsList //creating and defining temporary variables

    //some not necessary codes for this issue
    const questionIndex = randomNumber(neverAskedList.length)
    const firstQuestion = neverAskedList[questionIndex]

    let firstAnswers = []
    for (let i = 0; i < 4; i  ) {
      let answerIndex = randomNumber(allWordsList.length)
      firstAnswers[i] = allWordsList[answerIndex]
      allWordsList.splice(answerIndex, 1)//and here! I'm removing this record to prevent using it again next time, there will be different answers always
    }

    //some not necessary codes for this issue
    firstAnswers.push(firstQuestion)
    const randomisedAnswers = firstAnswers.sort(()=>Math.random() - 0.5)

    //some not necessary codes for this issue
    setQuestion(firstQuestion)
    setAnswers(randomisedAnswers)

    //and then here! I'm removing the used question in this time to prevent using it again, there will be different questions always and never see this question again 
    neverAskedList.splice(questionIndex, 1)
    setNeverAskedWords(neverAskedList)
    
  }

allWords should'nt change. But changing, because of why?

CodePudding user response:

So the most obvious thing that I see in your code is that you are modifying the same object. What you should do instead is use the spread operator.

const [allWords, setAllWords] = useState([])
const [neverAskedWords, setNeverAskedWords] = useState([])

async function getAllData(){
    
    axios
    .get(`http://127.0.0.1:3000/api/improve-language`)
    .then(res => {
      setAllWords(res.data)//defining allWords
      setNeverAskedWords(res.data)//defining neverAskedWords
      firstQuestionAndAnswers(res.data)//sending all datas by parameter, bacause when I'm trying to get datas by using `allWords` state, it would be undefined. That's why sending all data by parameter for the first time to set first question and answers.
    })
    .catch(err =>{
      console.log(err)
    })

  }

async function firstQuestionAndAnswers(wordsList){
    // don't use await for js objects, should be used only with promises.
    // use spread operator to make copy of the wordList array so you never actually modify the original object
    let neverAskedList = [...wordsList]
    const allWordsList = [...wordsList]

    //some not necessary codes for this issue
    const questionIndex = randomNumber(neverAskedList.length)
    const firstQuestion = neverAskedList[questionIndex]

    let firstAnswers = []
    for (let i = 0; i < 4; i  ) {
      let answerIndex = randomNumber(allWordsList.length)
      firstAnswers[i] = allWordsList[answerIndex]
      allWordsList.splice(answerIndex, 1)//and here! I'm removing this record to prevent using it again next time, there will be different answers always
    }

    //some not necessary codes for this issue
    firstAnswers.push(firstQuestion)
    const randomisedAnswers = firstAnswers.sort(()=>Math.random() - 0.5)

    //some not necessary codes for this issue
    setQuestion(firstQuestion)
    setAnswers(randomisedAnswers)

    //and then here! I'm removing the used question in this time to prevent using it again, there will be different questions always and never see this question again 
    neverAskedList.splice(questionIndex, 1)
    setNeverAskedWords(neverAskedList)
    
  }

If you don't understand why it happened then here's a short explanation. In js when you do const a = { key: 'val' } you created a variable that references the memory block that is actually storing your object. And when you do const b = a you are creating another variable that references the same memory block. So updating 1 automatically changes the other one.

  • Related