简体   繁体   English

Reactjs 中的 setState() 更新多个属性而不是一个

[英]setState() in Reactjs updating multiple properties instead of one

When I update 'classProficienciesChoices' in my state using setState() it is updating not only that property, but also where I derived the 'classProficienciesChoices' info from in the 'classSelected' property, AND ALSO from where I derived the classSelected info from in the 'classesInfo' property.当我使用 setState() 在我的状态中更新“classProficienciesChoices”时,它不仅更新该属性,而且更新我从“classSelected”属性中导出“classProficienciesChoices”信息的位置,以及我从中导出 classSelected 信息的位置'classesInfo' 属性。

The same function I update 'classProficienciesChoices' I also update 'classProficiencies', and it updates properly in the one property I tell it to, and not the elements where the information was derived from.我更新“classProficienciesChoices”的同一个函数我也更新“classProficiencies”,它在我告诉它的一个属性中正确更新,而不是在派生信息的元素中。

Any insight would be helpful.任何见解都会有所帮助。 The Create component has other components nested and none of them have state and only use props passed. Create 组件嵌套了其他组件,它们都没有状态,只使用传递的道具。 There are navigation, selection, and information display components nested.嵌套有导航、选择和信息显示组件。

import React, { Component } from 'react'
import Create from './Create'

class App extends Component {
    constructor(props) {
        super(props);
        const url = 'http://www.dnd5eapi.co/api/';

        fetch(url + 'classes')
            .then(result => result.json())
            .then(result => { this.setState({ classes: result, }, this.getInfo(result)) });
    }

    state = {
        classes: {}, //assigned value from API call in constructor
        classesInfo: [], //assigned value from API call in getInfo()
        classSelected: {}, //assigned a value derived from classInfo in displayClassInfo()
        classProficiencies: [],   //assigned a value derived from classSelected in setStartingProficiencies()
        classProficienciesChoices: [],  //assigned a value derived from classSelected in setStartingProficiencies()
    } 

    getInfo(data) {
        let info = []
        const url = 'http://www.dnd5eapi.co'
        for (var i = 0; i < data.results.length; i++) {
            fetch(url + data.results[i].url)
                .then(result => result.json())
                .then(result => info.push(result))
        }
        this.setState({ classesInfo: info, })
        }
    }

    setStartingProficiencies(chosenClass) {

        const profs = chosenClass.proficiencies.map((prof) => {
            return prof;
        });
        const proChoice = chosenClass.proficiency_choices.map((choices) => {
            return choices;
        });

        this.setState({ classProficiencies: profs, classProficienciesChoices: proChoice, });        
    } 

    addProficiency = (proficiencyName) => { 
        const { classProficienciesChoices } = this.state
        // classProficienciesChoices: [
        //        { choose: 2, type: 'proficiencies', from: [{ name: 'someName', url: 'someUrl' }, { name: 'someName', url: 'someUrl' }] },
        //          ]
        // different classes have more objects in the parent array

        let newChoiceArray = classProficienciesChoices.map((choices) => {
            return choices
        })

        for (var i = 0; i < newChoiceArray.length; i++) { 
            for (var j = 0; j < newChoiceArray[i].from.length; j++) {
                if (newChoiceArray[i].from[j].name === proficiencyName) {

                    let newChoices = newChoiceArray[i].from.filter(function (proficiency) { return proficiency.name !== pIndex })
                    let newProficiency = newChoiceArray[i].from.filter(function (proficiency) { return proficiency.name === pIndex })

                    newChoiceArray[i].from = newChoices //I think this is the problem

                    this.setState(state => ({
                        classProficiencies: [...state.classProficiencies, newProficiency[0]],
                        proficienciesChoices: newChoiceArray,
                    }))
                }
            }
        }
    }

    displayClassInfo = index => {
        const { classesInfo } = this.state
        for (let i = 0; i < classesInfo.length; i++) {
            if (classesInfo[i].index === index) {
                const classSelected = classesInfo.filter(function (cClass) { return cClass.name === classesInfo[i].name })
                this.setState({ classSelected: classSelected[0], isClassSelected: true }, this.setStartingProficiencies(classSelected[0]),)
                break;
            }
        }
    }

    render() {

        const { classes, classesInfo, classSelected, isClassSelected, classProficiencies, classProficienciesChoices } = this.state

        return (<Create classes={classes} classesInfo={classesInfo} displayClassInfo={this.displayClassInfo} classSelected={classSelected} isClassSelected={isClassSelected} category='classes' classProficiencies={classProficiencies} classProficienciesChoices={classProficienciesChoices} addProficiency={this.addProficiency} />);

    }
}

export default App

你调用 setState 四次,当然它会多次更新状态。

SOLVED!!!解决了!!! Stumbled across turning the array into a string and then back.偶然发现将数组变成字符串然后返回。 It breaks the reference and creates an entirely new array.它打破了引用并创建了一个全新的数组。 Reference type got me.引用类型得到了我。

setStartingProficiencies(chosenClass) {

        const proficiencies = JSON.parse(JSON.stringify(chosenClass.proficiencies))
        const proficienciesChoices = JSON.parse(JSON.stringify(chosenClass.proficiency_choices))    

        this.setState({ classProficiencies: proficiencies, classProficienciesChoices: proficienciesChoices, });

    } 

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

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