简体   繁体   English

无线电输入重复选择(反应)

[英]radio inputs repeating on selection (React)

I'm trying to make a single question quiz app with react on codepen.我正在尝试制作一个对 codepen 做出反应的单一问题测验应用程序。 I'm using an api to get a question, 3 incorrect answers and a correct answer to the question and adding it to the state.我正在使用 api 来获取问题、3 个错误答案和问题的正确答案并将其添加到状态中。 I am having an issue while validating the answer.我在验证答案时遇到问题。 After clicking on one of the 4 options, I want to conditionally render a div with the result.单击 4 个选项之一后,我想有条件地用结果渲染一个 div。 But the issue is that after the result is displayed, another radio input is getting rendered.但问题是,在显示结果后,正在呈现另一个无线电输入。

 const appRoot = document.getElementById('app'); class App extends React.Component{ state={ question:'', correct:'', incorrect:[], result: null } componentDidMount(){ axios.get('https://opentdb.com/api.php?amount=1&type=multiple') .then(res => { const data = res.data.results[0]; const q = data.question; const correct = data.correct_answer; const incorrect = data.incorrect_answers; this.setState({question:q,correct:correct,incorrect:incorrect}) }) } evaluate(selected){ if(selected === this.state.correct){ this.setState({result: 'Correct!'}) } else { this.setState({result:`Wrong! Correct Answer is ${this.state.correct}`}) } } render(){ const random = Math.floor(Math.random() * 3); const options = this.state.incorrect; options.splice(random, 0, this.state.correct); const choices = options.map((option,i) => ( <div> <input type='radio' name='option' value={option} key={i} onChange={() => this.evaluate(option)}/> <label for='option'>{option}</label> </div> ) ) return( <div> <div>{this.state.question}</div> <div>{choices}</div> <div>{this.state.result}</div> </div> ) } } ReactDOM.render(<App />, appRoot)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <div id='app'></div>

This seems like an honest mistake (one I am guilty of consistently):这似乎是一个诚实的错误(我一直犯的一个错误):

In your render method you mutate your array:在你的render方法中,你改变了你的数组:

const options = this.state.incorrect;
options.splice(random, 0, this.state.correct);

I suspect what you want is:我怀疑你想要的是:

const options = this.state.incorrect.slice(); //create a COPY of the array
options.splice(random, 0, this.state.correct);

React is basically a state machine that looks for changes to the state and intelligently updates parts that depend on that state. React 基本上是一个状态机,它寻找状态的变化并智能地更新依赖于该状态的部分。 But it is just JavaScript.但它只是 JavaScript。 By directly splicing the state object you're changing the state in the render method.通过直接拼接状态对象,您正在更改渲染方法中的状态。 React doesn't know you changed the state and as such, you're ending up with unexpected behaviors--particularly as render is called frequently. React 不知道您更改了状态,因此,您最终会出现意外行为——尤其是在频繁调用render

I've copied your snippet so you can see a working example.我已经复制了你的代码片段,所以你可以看到一个有效的例子。

 const appRoot = document.getElementById('app'); class App extends React.Component{ state={ question:'', correct:'', incorrect:[], result: null } componentDidMount(){ axios.get('https://opentdb.com/api.php?amount=1&type=multiple') .then(res => { const data = res.data.results[0]; const q = data.question; const correct = data.correct_answer; const incorrect = data.incorrect_answers; this.setState({question:q,correct:correct,incorrect:incorrect}) }) } evaluate(selected){ if(selected === this.state.correct){ this.setState({result: 'Correct!'}) } else { this.setState({result:`Wrong! Correct Answer is ${this.state.correct}`}) } } render(){ const random = Math.floor(Math.random() * 3); const options = this.state.incorrect.slice(); options.splice(random, 0, this.state.correct); const choices = options.map((option,i) => ( <div> <input type='radio' name='option' value={option} key={i} onChange={() => this.evaluate(option)}/> <label for='option'>{option}</label> </div> ) ) return( <div> <div>{this.state.question}</div> <div>{choices}</div> <div>{this.state.result}</div> </div> ) } } ReactDOM.render(<App />, appRoot)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <div id='app'></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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