Home > database >  Use state in React causing value of const to break
Use state in React causing value of const to break

Time:04-20

I'm trying to make an app where the user can cycle through a pack of cards. I'm trying to make it so each card is unique so that a user cannot pick two of the same card consecutively. Therefore the way I thought of doing this was by adding all the cards to an array and then shuffling that array.

import * as React from "react";
import { View, Text, Button } from "react-native";
import homeStyles from "../styles/homeStyles";
import { cardsList } from "../assets/cardsList";
import { useEffect, useState } from "react";

export default function Home() {
  const [CurrentQuestion, setCurrentQuestion] = useState(1);
  const [usedQuestions, setUsedQuestions] = useState([]);
  const test = [];

  const length = cardsList.length;

  const shuffle = () => {
    let i,
      x = 0,
      y = 0,
      temp0 = 0;
    for (i = 0; i < usedQuestions.length; i  ) {
      x = Math.floor(Math.random() * usedQuestions.length);
      y = Math.floor(Math.random() * usedQuestions.length);
      if (x === y) {
        //for dont change arr[index] with self !!!
        continue;
      }
      temp0 = usedQuestions[x];
      usedQuestions[x] = usedQuestions[y];
      usedQuestions[y] = temp0;
    }
    console.log("Shuffled : "   usedQuestions);
  };

  let i = 0;
  const nextQuestion = () => {
    let plz = null;
    if (i <= usedQuestions.length) {
      // plz = usedQuestions[i]
      setCurrentQuestion(usedQuestions[i]);
      i = i   1;
    } else {
      i = 0;
      // shuffle()
      // nextQuestion()
    }
    // console.log(plz)
    console.log(CurrentQuestion);
  };

  const start = () => {
    let i = 1;
    while (i <= length) {
      test.push(i);
      i  ;
    }
    console.log("initial : "   test);
    setUsedQuestions([...usedQuestions, ...test]);
  };

  return (
    <View style={homeStyles.container}>
      <View style={homeStyles.card}>
        {cardsList
          .filter(function (item) {
            return item.id === CurrentQuestion;
          })
          .map((cardsList) => {
            return (
              <View key={cardsList.id}>
                <View style={homeStyles.line}>
                  <Text style={homeStyles.cardNumber}>
                    {cardsList.id}) {cardsList.title}
                  </Text>
                </View>
                <Text style={homeStyles.cardText}>{cardsList.cardText}</Text>
              </View>
            );
          })}
        <Button
          style={homeStyles.button}
          title="Shuffle"
          onPress={() => shuffle()}
        />
        <Button
          style={homeStyles.button}
          title="Next Question"
          onPress={() => nextQuestion()}
        />
        <Button
          id="test"
          style={homeStyles.button}
          title="Start"
          onPress={() => start()}
        />
      </View>
    </View>
  );
}

The section below is the section causing me issues

let i = 0;
const nextQuestion = () => {
  let plz = null;
  if (i <= usedQuestions.length) {
    // plz = usedQuestions[i]
    setCurrentQuestion(usedQuestions[i]);
    i = i   1;
  } else {
    i = 0;
    // shuffle()
    // nextQuestion()
  }
  // console.log(plz)
  console.log(CurrentQuestion);
};

The const plz works perfectly returning the value of the cards one by one from the shuffled array. See Image Const plz working

However when I try and use the UseState feature from react to set this value so that I can use it to display the correct part in the app section it breaks. Use state breaks value

Any idea why this happens and how I can fix it? I'm fairly new to coding so any tips on how I could better it would be appreactiated.

CodePudding user response:

You cannot modify a state directly

You can create a copy, shuffle it and reassign the state in this way

const shuffle = () => {
   setUsedQuestion(u => {
    const data = [...u]
    data.sort(() => Math.random() - 0.5))
    console.log("Shuffled : "   data);
    return data;
    }
   )
}

CodePudding user response:

Everytime you update a react state (eg. by calling setCurrentQuestion) your component will rerender.
Here, rerendering means it will execute the code of your function component again (function Home()).
In the body of function Home() you have this: let i = 0; so i will reset everytime you change a local state.

Now what you probably want is to persist the current question index across multiple rerenders.

you could do nextQuestion like this:

// remove: const [CurrentQuestion, setCurrentQuestion] = useState(1);
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const currentQuestion = usedQuestions[currentQuestionIndex];

const nextQuestion = () => {
  if (currentQuestionIndex < usedQuestions.length) {
    setCurrentQuestionIndex(currentQuestionIndex   1);
  } else {
    setCurrentQuestionIndex(0);
  }
};

You might have more tweaking to do but that should get you started

  • Related