Массив в состоянии заменяется на 1 при установке состояния - PullRequest
1 голос
/ 28 мая 2020

Я новичок в React, поэтому заранее прошу прощения, если я пытаюсь сделать что-то, что невозможно сделать. Я пытаюсь сохранить объект, содержащий идентификатор и оценку для выбора в массиве «scores» в состоянии. Я создаю объект в функции, называемой handleScore, и состояние, кажется, отображается правильно, когда я впервые нажимаю на выбор и сразу же записываю массив очков на консоль, но когда я записываю массив очков на консоль в рендере метода, я просто получаю 1. Я также получаю 1, когда делаю выбор, а затем снова нажимаю кнопку. Есть ли у кого-нибудь идеи, что происходит? Вот код:

    handleScore = (id, score, idx) => {
        const { statements, scores } = this.state;
        let scoreObj = {};

        Object.assign(scoreObj, {'id': id, 'score': score});

        if (statements[0][idx].isSelected) {
            this.setState({
                scores: scores[0].push(scoreObj)
            });
            console.log("scores array: ", scores[0]); //outputs an array containing [{id: "O1", score: "4"}]
        } else {
            console.log("scores array: ", scores[0]); // outputs 1
        }
    }

В методе render ():

        render() {
            console.log("this.state.scores from render method: ", this.state.scores); // outputs 1 instead of [{id: "O1", score: "4"}]
            return (
                <div>
                    <div className="statements-wrapper">
                        {
                            this.state.statements[0].map((item, index) => (
                                    <div
                                    key={item.id} onClick={(e) => {
                                                e.preventDefault();
                                                this.handleScore(item.id, match.params.score, index)
                                            }}>
                                        <a href="#">{item.statement}</a>
                                    </div>
                                )
                            )
                        }
                    </div>
                </div>
            )

ожидаемый результат:

            scores: [
                [{id: "O1", score: 4}, {id: "G1", score: 3}, {id: "B1", score: 2}, {id: "R1", score: 1}],
                [{id: "O2", score: 4}, {id: "G2", score: 3}, {id: "B2", score: 2}, {id: "R2", score: 1}],
                [{id: "O3", score: 4}, {id: "G3", score: 3}, {id: "B3", score: 2}, {id: "R3", score: 1}],
                [{id: "O4", score: 4}, {id: "G4", score: 3}, {id: "B4", score: 2}, {id: "R4", score: 1}],
                [{id: "O5", score: 4}, {id: "G5", score: 3}, {id: "B5", score: 2}, {id: "R5", score: 1}]
            ]

1 Ответ

0 голосов
/ 28 мая 2020

Я думаю, что проблема связана с заменой всего this.state.scores на один массив, когда вы используете setState. Чтобы сохранить остальные массивы элементов, вы хотите сделать что-то вроде:

handleScore = (id, score, idx) => {
    const { statements, scores } = this.state;
    if (statements[0][idx].isSelected) {
        // this assumes you want to append the first array (hence 'index === 0') in this.state.scores
        this.setState({
            scores: scores.map((item, index) => index === 0 ? [...item, {'id': id, 'score': score}] : item)
        });
    }
}

Также важно отметить, что метод выше, а также push поместит новый объект в end массива, а setState является асинхронным, поэтому ведение журнала scores сразу после этого может быть ненадежным.

Чтобы удалить указанный объект c в одном из внутренних массивов, вы можно использовать фильтр :

// replacing an inner object by id value
scores.map((item, index) => index === 0 ? 
  item.filter((i) => i.id !== "01")
  : item
)
...