简体   繁体   中英

How can I pass data from a React component to main file?

I am having trouble passing data from component to main file in react. It is a basic quiz application, get quiz objects from api and pass data to the "Question" component. In the main file i have score state to decide how many answers are correct. But when answer button clicked application see value in the component. I want to match answer value and correct answer and increase score by state. Here is the Question component and main file.

export default function Question(props) {

const [flag,setFlag] = React.useState(true)

// TOGGLE BUTTON BACKGROUND COLOR WHEN BTN CLICKED
function toggleBtnBgColor(btn) {
    if(flag) {
        btn.target.classList.toggle("dark-bg-color")
        setFlag(false)
    }
}

return (
    <>
        <div className="question" key={props.index}>{props.question}</div>
            {props.answers.map((answer,index)=> {
                return (
                    <button key={index} onClick={toggleBtnBgColor} className="answer-button">{answer}</button>
                )
        })}
        <hr></hr>
    </>
)

}

Main file;

const [data, setData] = React.useState([])
const [score, setScore] = React.useState(0)
const [startAgain, setStartAgain] = React.useState(false)

// FETCH QUIZ DATA FROM API
const fetchData = async () => {
    await fetch("https://opentdb.com/api.php?amount=5&type=multiple")
    .then((response) => response.json())
    .then((data) => setData(data.results))
}

React.useEffect(()=> {
    fetchData()
},[])

// SHUFFLE ALGORITHM TO USE LATER
function shuffle(array) {
    let currentIndex = array.length,  randomIndex;
  
    // While there remain elements to shuffle.
    while (currentIndex != 0) {
      // Pick a remaining element.
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex--;
      // And swap it with the current element.
      [array[currentIndex], array[randomIndex]] = [
        array[randomIndex], array[currentIndex]];
    }
    return array;
}

// RENDER QUESTIONS
const questionElements = data.map((question, index) => {
    // ANSWERS ARRAY AND SHUFFLE
    let answers = [...question.incorrect_answers,question.correct_answer]
    shuffle(answers)

    return (
        <Question key={index} index={index} question={question.question} answers={answers}/>
    )
})

// CALCULATE FINAL SCORE WHEN CHECK BTN CLICKED
function calcScore() {
    for(let question of questionElements) {
        console.log(question.calcScore)
    }
    setStartAgain(true)
}

return (
    <div className="question-container">
        {questionElements}
        <p>{startAgain && ("Your score is "+ score +"/5")}</p>
        <button onClick={calcScore} className="check-button">{!startAgain ? "Check Answers" : "Restart Quiz"}</button>
    </div>
)

Check this out, we pass a function to Question that receives the answer and index. The parent will update an array that carries all the answers

https://codesandbox.io/s/black-cdn-p6lo5v?file=/src/App.js

const setAnswer = (index, answer) => {
  const newAnswers = [...answers];
  newAnswers[index] = answer;
  setAnswers(newAnswers);
};


// RENDER QUESTIONS
const questionElements = data.map((question, index) => {
  // ANSWERS ARRAY AND SHUFFLE
  let answers = [...question.incorrect_answers, question.correct_answer];
  shuffle(answers);

  return (
    <Question
      key={index}
      index={index}
      question={question.question}
      answers={answers}
      setAnswer={setAnswer}
    />
  );
});

If I am not wrong I understand that you want to update parent component's state. You can pass setState function as props to child component like this:

 return ( <Question key={index} index={index} question={question.question} answers={answers} updateScore ={setScore}/> )

  1. You can make use of props for the same and pass setScore hook to set the values.
  2. You can make use of Redux and get/set the values to/from it.

Most people prefer redux over passing the setState hooks to children as props, however many times people pass the hook as props and solve this.

Hope this helps you!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM