[英]How can I have each of my my quiz questions and their choices in different pages in react by axios
I am very new in React.我对 React 很陌生。 I am preparing a quiz.
我正在准备测验。 I have my questions and their choices at the same page.
我在同一页面上有我的问题和他们的选择。 What I want is to have each questions with their choices in different pages.
我想要的是在不同的页面中让每个问题都有自己的选择。 After a button click to a choice I want to pass to the next page's question.
单击按钮选择一个选项后,我想转到下一页的问题。 How can I do that?
我怎样才能做到这一点?
import React from "react";
import axios from "axios";
function Question(props) {
this.state = { questionNumber: 0 };
let style = {
margin: "5px"
};
clickHandler = () => {};
return (
<div className="Question">
<h4>{props.question}</h4>
<ul>
{props.choices.map((c, i) => (
<button style={style} clickHandler={this.clickHandler}>
{c.choice}
</button>
))}
</ul>
</div>
);
}
class QuizApp extends React.Component {
constructor(props) {
super(props);
this.state = { questions: [], choices: [] };
}
componentDidMount() {
axios
.get(
"https://private-anon-c06008d89c-quizmasters.apiary-mock.com/questions"
)
.then(response => {
this.setState({ questions: response.data });
});
}
render() {
return <div>{this.state.questions.map(q => new Question(q))}</div>;
}
}
Not quite different pages, but you can use the array of questions and answers to give the illusion of different pages, but all in the same component.不是完全不同的页面,但您可以使用一系列问题和答案来提供不同页面的错觉,但都在同一个组件中。 Just display one element at a time.
一次只显示一个元素。 For example, say
response.data
from your get request is as follows:例如,假设您的 get 请求中的
response.data
如下:
[
{
question: 'What is question 1?',
option1: 'Option 1',
option2: 'Option 2',
option3: 'Option 3'
},
{
question: 'What is question 2?',
option1: 'Option 1',
option2: 'Option 2',
option3: 'Option 3'
},
{
question: 'What is question 3?',
option1: 'Option 1',
option2: 'Option 2',
option3: 'Option 3'
},
]
You want to display one index of that arrat ay a time, so you will need another state attribute called currentQuestionIndex
.您希望每次都显示该 arrat 的一个索引,因此您需要另一个名为
currentQuestionIndex
状态属性。 Start that with 0, so that it can start at the first question from that array.从 0 开始,以便它可以从该数组的第一个问题开始。
You also need somewhere to store your answers as you go, so, we'll add an answers
state attribute.您还需要在某个地方存储您的答案,因此,我们将添加一个
answers
状态属性。 Both of these should be defined in the constructor, which will now look like this:这两个都应该在构造函数中定义,现在看起来像这样:
constructor (props, context) {
super(props, context)
this.state = {
currentQuestionIndex: 0,
questions: [],
answers: []
}
}
The questions
state attribute needs to be set in your componentDidMount
, so that part in your code looks good so far.需要在您的
componentDidMount
设置questions
状态属性,以便您的代码中的部分到目前为止看起来不错。
We set up the render part so that it only displays whatever question is on the currentQuestionIndex
.我们设置了渲染部分,以便它只显示
currentQuestionIndex
上的任何问题。 I will also already add the Next button so you can navigate to the next question.我还将添加“下一步”按钮,以便您可以导航到下一个问题。
It should look something like this:它应该是这样的:
render() {
const { questions, currentQuestionIndex, answers } = this.state
const { question, option1, option2, option3} = questions[currentQuestionIndex]
return (<div>
<h4>{question}</h4>
<label>
<input type='radio'
value={option1}/>
{option1}
</label>
<br/>
<label>
<input type='radio'
value={option2}/>
{option2}
</label>
<br/>
<label>
<input type='radio'
value={option3}/>
{option3}
</label>
<hr/>
<button>Next</button>
</div>);
}
Cool!凉爽的! Now we need to make this radio input buttons actually work by adding the
checked
prop and adding a handler.现在我们需要通过添加
checked
prop并添加处理程序来使这个单选输入按钮实际工作。 This is where our answers
state comes into play.这就是我们的
answers
状态发挥作用的地方。 The checked
prop is a boolean, so we want a radio button to be checked whenever their current value is in the same index they are in the answers
array.被
checked
道具是一个布尔值,所以我们想要一个单选按钮,只要它们的当前值与它们在answers
数组中的索引相同,就会被检查。 So this is what our handler will look like:所以这就是我们的处理程序的样子:
onChangeOption (value) {
const { currentQuestionIndex } = this.state
let answers = [...this.state.answers]
answers[currentQuestionIndex] = value
this.setState({answers})
}
Lets update our render function to incorporate the checked
prop and the onChangeOption
function:让我们更新我们的渲染函数以合并
checked
prop 和onChangeOption
函数:
render() {
const { questions, currentQuestionIndex, answers } = this.state
const { question, option1, option2, option3} = questions[currentQuestionIndex]
return (<div>
<h1>Question {currentQuestionIndex + 1}</h1>
<h4>{question}</h4>
<label>
<input type='radio'
checked={answers[currentQuestionIndex] === option1}
value={option1}
onChange={(evt) => this.onChangeOption(evt.target.value)}/>
{option1}
</label>
<br/>
<label>
<input type='radio'
checked={answers[currentQuestionIndex] === option2}
value={option2}
onChange={(evt) => this.onChangeOption(evt.target.value)}/>
{option2}
</label>
<br/>
<label>
<input type='radio'
checked={answers[currentQuestionIndex] === option3}
value={option3}
onChange={(evt) => this.onChangeOption(evt.target.value)}/>
{option3}
</label>
<hr/>
<button>Next</button>
</div>);
}
That should take care of our question handling in that page.这应该照顾我们在该页面中的问题处理。 But how should we change the page?
但是我们应该如何更改页面呢? Lets work on that Next button, shall we?
让我们处理下一个按钮,好吗?
As mentioned previously, what defines what question is displayed is through it's index using the currentQuestionIndex
, so upon clicking on the next button, lets increment that.如前所述,定义显示的问题是通过使用
currentQuestionIndex
的索引,因此在单击下一个按钮时,让我们增加它。 Here is the onClick handler:这是 onClick 处理程序:
handleNext () {
let incrementCurrentQuestionIndex = this.state.currentQuestionIndex + 1
this.setState({currentQuestionIndex: incrementCurrentQuestionIndex})
}
This is what the next button should look like:这是下一个按钮的样子:
<button onClick={() => this.handleNext()}>Next</button>
Finally, lets add a few final touches so that this little app can function properly:最后,让我们添加一些最后的修饰,以便这个小应用程序能够正常运行:
1- Since you are only getting your questions on the componentDidMount
lifecycle method you will need to add a placeholder while your questions are still loading. 1- 由于您只收到有关
componentDidMount
生命周期方法的问题,因此您需要在问题仍在加载时添加占位符。 So inside the render()
method, before rendering your questions, you want to check to see if the questions
state is already filled in. Something like this:所以在
render()
方法中,在呈现你的问题之前,你想检查一下questions
状态是否已经填写。像这样:
render() {
const { questions, currentQuestionIndex, answers } = this.state
// Will be rendered before you grab all your questions
if (!questions.length) {
return <div> Loading questions...</div>
}
// Do the rest...
}
2- Next, you may want to disable the Next button once your array is at it's end. 2-接下来,一旦您的阵列结束,您可能想要禁用“下一步”按钮。 Of course in your actual app, you will handle it differently, but you need to make sure you don't pass the size of the questions array.
当然,在您的实际应用程序中,您会以不同的方式处理它,但您需要确保不传递问题数组的大小。 For this example, we just disable the Next button, so it will look like this:
在这个例子中,我们只是禁用了 Next 按钮,所以它看起来像这样:
<button disabled={currentQuestionIndex === questions.length - 1} onClick={() => this.handleNext()}>Next</button>
Update: This had an awkward flow, so for this example, it would probably be better just to display a different page when you run out of questions.更新:这有一个尴尬的流程,所以对于这个例子,当你用完问题时,最好只显示一个不同的页面。 To do this, on your
render()
function, just add a condition which displays something saying the quiz has ended if the currentQuestionIndex is larger or has reached the size of the questions array.为此,在您的
render()
函数上,只需添加一个条件,如果 currentQuestionIndex 较大或已达到问题数组的大小,则该条件显示测验已结束。 So something like this BEFORE your questions being rendered:所以在你的问题被呈现之前是这样的:
if (currentQuestionIndex >= questions.length) {
return (
<div>
<h3>End of the Quiz!</h3>
</div>
)
}
The example app has been updated accordingly as well.示例应用程序也已相应更新。
tl;dr: Take advantage of the array of questions you get. tl;dr:利用你得到的一系列问题。 Only display the question and options of the current index you are on.
仅显示您所在的当前索引的问题和选项。 When you want to move on the next one, just increment the current index by clicking the button.
当您想继续下一个时,只需单击按钮增加当前索引。
Here is the fully functional example app:这是功能齐全的示例应用程序:
//Simulating data coming from axios const questionsArray = [ { question: 'What is question 1?', option1: 'Option 1', option2: 'Option 2', option3: 'Option 3' }, { question: 'What is question 2?', option1: 'Option 1', option2: 'Option 2', option3: 'Option 3' }, { question: 'What is question 3?', option1: 'Option 1', option2: 'Option 2', option3: 'Option 3' }, ] class App extends React.Component { constructor (props, context) { super(props, context) this.state = { currentQuestionIndex: 0, questions: [], answers: [] } } componentDidMount() { // Do your axios call and set the questions state. // For the sake of simplicity,I'll be using my array. this.setState({questions: questionsArray}) } handleNext () { let incrementCurrentQuestionIndex = this.state.currentQuestionIndex + 1 this.setState({currentQuestionIndex: incrementCurrentQuestionIndex}) } onChangeOption (value) { const { currentQuestionIndex } = this.state let answers = [...this.state.answers] answers[currentQuestionIndex] = value this.setState({answers}) } render() { const { questions, currentQuestionIndex, answers } = this.state if (!questions.length) { return <div> Loading questions...</div> } if (currentQuestionIndex >= questions.length) { return ( <div> <h3>End of the Quiz!</h3> </div> ) } const { question, option1, option2, option3} = questions[currentQuestionIndex] return (<div> <h1>Question {currentQuestionIndex + 1}</h1> <h4>{question}</h4> <label> <input type='radio' checked={answers[currentQuestionIndex] === option1} value={option1} onChange={(evt) => this.onChangeOption(evt.target.value)}/> {option1} </label> <br/> <label> <input type='radio' checked={answers[currentQuestionIndex] === option2} value={option2} onChange={(evt) => this.onChangeOption(evt.target.value)}/> {option2} </label> <br/> <label> <input type='radio' checked={answers[currentQuestionIndex] === option3} value={option3} onChange={(evt) => this.onChangeOption(evt.target.value)}/> {option3} </label> <hr/> <button onClick={() => this.handleNext()}>Next</button> </div>); } } ReactDOM.render( <App />, document.getElementById('app') );
<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> <div id="app"></div>
Take a look at this example:看看这个例子:
https://codesandbox.io/s/km4538r82r https://codesandbox.io/s/km4538r82r
from this lib:从这个库:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.