在状态数组中使用状态索引

时间:2019-04-04 10:00:20

标签: reactjs

我试图使用状态索引显示状态数组的特定值,但是当我更新索引的状态时,组件不会重新呈现。

我的代码将帮助您了解:

export default class Game extends Component {
    state = {
        nbTours: 10,
        tourAct: 0,
        questions: [],
        currentQuestion: 0,

        robotIntegrity: 100,
        robotName: "RobotName"
    }

    [...]

    render()
    {
        [...]

        return (
            <>
            <Card style={{ width: '20rem', marginBottom: "1em" }}>
                <Card.Header as="h4">
                    Tours : {this.state.tourAct} / {this.state.nbTours}
                </Card.Header>
                <Card.Body className="robot-infos">
                    <h5 style={{ marginBottom: '1em' }}>{this.state.robotName}</h5>

                    Intégrité du robot :
                    <div class="progress" style={{ marginTop: '1em', height: "2em" }}>
                      <div class="progress-bar progress-bar-striped" role="progressbar" style={{ width: this.state.robotIntegrity + '%'}} aria-valuenow={this.state.robotIntegrity} aria-valuemin="0" aria-valuemax="100"><b>{this.state.robotIntegrity}%</b></div>
                    </div>
                </Card.Body>
            </Card>

            {this.state.questions[this.state.currentQuestion]}
            </>
        )
    }
}

questions: []是一个Question组件数组,显示了我想要的样子,并带有正确的值。唯一的问题是,当我想要时,它不会更新DOM。

在更新currentQuestion索引时应该如何重新呈现组件?

完成Game.js:

import React, { Component } from 'react';
import JsonData from './data/questions2.json'
import Question from './components/QuestionComponent';
import Answer from './components/AnswerComponent';
import { Card } from 'react-bootstrap';

export default class Game extends Component {
    state = {
        nbTours: 10,
        tourAct: 0,
        questions: [],
        currentQuestion: 0,

        robotIntegrity: 100,
        robotName: "RobotName"
    }

    /**
     * Met a jour la question actuelle
     */
    updateCurrentQuestion = () => {
        let rand = Math.floor(Math.random() * this.state.questions.length);
        this.setState({currentQuestion: rand})
    }

    /**
     * Passe au prochain tour
     */
    nextTour = (valInteg) => {
        if(this.state.tourAct < this.state.nbTours)
        {
            this.setState(prevState => ({
                tourAct: prevState.tourAct+1,
            }));
        }
        else
        {
            this.endGame();
        }
        this.updateIntegrity(valInteg);
        this.updateCurrentQuestion()
    }

    /**
     * Fin de la partie avec victoire
     */
    endGame = () => {
        return (<h2>Fin de la partie, vous avez gagné</h2>)
    }

    /**
     * Fin de la partie défaite
     */
    gameOver = () => {
        return (<h2>Fin de la partie : Votre robot s'est autodétruit !</h2>)
    }

    /**
     * Met a jour l'intégrité du robot
     */
    updateIntegrity = (val) => {
        if(this.state.robotIntegrity + val >= 100)
        {
            this.setState({robotIntegrity: 100});
        }
        else if(this.state.robotIntegrity + val <= 0)
        {
            this.setState({robotIntegrity: 0});
        }
        else{
            this.setState(prevState => ({
                robotIntegrity: prevState.robotIntegrity+val
            }))
        }   
    }

    /**
     * Récupere toutes les questiosn dans le fichier JSON et les transforme en composants Questions / Answer
     */
    componentDidMount()
    {
        JsonData.map((a) => {
            //réponses pour une question
            let reponses = a.reponses 
            //tableau de composants Answer
            let repComp = [];
            reponses.map((r) => {
                return repComp.push(<Answer callbackToParent={this.nextTour} text={r.rep} value={r.value}/>)
            })
            let question = <Question text={a.question} answers={repComp}/>
            this.setState((prevState) => ({
                questions: [...prevState.questions, question]
            }))
            return 0;
        })
        this.nextTour(0)
    }

    render()
    {
        let main;

        console.log(this.state.currentQuestion)
        console.log(this.state.tourAct + "/" + this.state.nbTours + " integrite : " + this.state.robotIntegrity)

        if(this.state.tourAct === this.state.nbTours && this.state.robotIntegrity > 0) 
        {
            main = this.endGame()
        }
        else if(this.state.robotIntegrity <= 0)
        {
            main = this.gameOver()
        }
        else
        {
            main = this.state.questions[this.state.currentQuestion];
        }

        console.log(this.state.questions)
        return (
            <>
            <Card style={{ width: '20rem', marginBottom: "1em" }}>
                <Card.Header as="h4">
                    Tours : {this.state.tourAct} / {this.state.nbTours}
                </Card.Header>
                <Card.Body className="robot-infos">
                    <h5 style={{ marginBottom: '1em' }}>{this.state.robotName}</h5>

                    Intégrité du robot :
                    <div class="progress" style={{ marginTop: '1em', height: "2em" }}>
                      <div class="progress-bar progress-bar-striped" role="progressbar" style={{ width: this.state.robotIntegrity + '%'}} aria-valuenow={this.state.robotIntegrity} aria-valuemin="0" aria-valuemax="100"><b>{this.state.robotIntegrity}%</b></div>
                    </div>
                </Card.Body>
            </Card>

            {this.state.questions[this.state.currentQuestion]}
            </>
        )
    }
}

1 个答案:

答案 0 :(得分:0)

也许我错过了它,但是在您的代码中看不到您实际更新currentQestion的位置。

天真的我会说调用this.setState({currentQestion: 4})应该导致重新渲染。

请参阅随附的示例:https://codesandbox.io/s/l5z19k94n7?fontsize=14