I'm building this simple quiz app in React where a random Korean hangul from a 40-item Data.json is displayed on the screen and users have 5 buttons with different answers which also come from Data.json.
For clarification, this is my application and the components I'm using. All components are siblings and live inside App.js.
What the application is suppose to do is to create a 5-item random array and select one of these as the right answer before render. If the user taps the right button all the components should be re-rendered with different items. That's why I decided to use the useEffect() hook.
But what is currently happening is:
- Every
console.logis being displayed twice in the console. The first time variables are empty and in the second time they display the values they should have; - The randomOptions array has 10 items instead of 5;
- If the
<Question/>component is in the code then I get errors andconsole.logtells me the values from myuseStatehooks are undefined. If<Question/>is removed I get the console shown in the picture below.
Console for clarification:
App.js component:
import './App.css';
import Data from './data/data.json';
import Header from './components/Header';
import Question from './components/Question';
import { useState, useEffect } from 'react';
function App() {
const [index, setIndex] = useState(Math.floor(Math.random() * 5)); // Tells us what the index of the right answer is
const [randomOptions, setRandomOptions] = useState([]); // Random array with 5 items from Data.json that are the options
const [question, setQuestion] = useState([]); // The question that goes to <Question/> and people need to guess
const randomizeButtonAnswer = () => {
let previousArray = randomOptions;
setRandomOptions([]);
for (let i=0; i < 5; i ){
let randomNumber = Math.floor(Math.random() * Data.length);
if (!randomOptions.includes(randomNumber) && !previousArray.includes(randomNumber)) {
setRandomOptions(randomOptions.push(randomNumber));
} else {
i--;
}
}
setRandomOptions(randomOptions.sort(() => Math.random() - 0.5));
setQuestion(randomOptions[index]);
}
useEffect(() => {
randomizeButtonAnswer();
}, [index])
console.log('index is ' index); // 3
console.log('randomOptions is ' randomOptions); // 33,9,3,26,8,20,0,12,29,25
console.log('question is ' question); //26
return (
<div className="App">
<Header />
<Question answer={question}/>
</div>
);
}
export default App;
Question.js component
import './Question.css';
import Data from '../data/data.json';
const Question = ({ answer }) => {
return (
<div className="question-wrapper">
<h1 className="question"><span className="highlight">{Data[answer].character}</span></h1>
<span>{Data[answer].character} = {Data[answer].char_id} </span>
</div>
);
}
export default Question;
I'm completely lost here. Not sure why things are being rendered twice or why when present <Question/> makes my variables become undefined. I assume something inside randomizeButtonAnswer is broken but I've been unable to find what exactly.
Small disclaimer: I'm a complete noob to React so if I'm doing something that is wrong or a bad practice do let me know.
Thanks for your time!
CodePudding user response:
I tried to fix your code but it's complicated and wrong at many points so I decided to write the function myself. Sorry about that.
there are many problem with your code.
- About log 2 times. It is
<StrictMode /> - You should understand more about React State. It not change right in the place you write it, it's queue up and update when your functions end. set 1 state 2 time in 1 function does not mean anything.
- Don't do
i--in for loop like that which is complicated to understand how things goes and hard to debug. use while loop or for best justdon't. check the condition and log out or have some handle for it. - Wanna log? log inside React Component? use
useEffect. - Default state of Question is not [].
- Always do conditional render if default value of state is possible be either
nullorundefined.
Good luck with your React journey.


