设置多个状态,并通过一个onClick函数推送到数组的状态

时间:2019-02-11 23:27:30

标签: javascript reactjs

我在代码中遇到了一个反复出现的问题,我想从组件中获取多条数据以设置为状态,然后将它们压入一个状态已更新的数组中。我目前的工作方式目前行不通,我认为这是因为我不了解js发生事件并做出反应的顺序。

以下是我正在执行的操作的一个示例,该示例无效:jsfiddle here或下面的代码。

import React, {Component} from 'react';

class App extends Component {

    constructor(props) {
        super(props);

        this.state = {
            categoryTitle: null,
            categorySubtitle: null,
            categoryArray: [],
        }
    }

    pushToCategoryArray = () => {
        this.state.categoryArray.push({
            'categoryTitle': this.state.categoryTitle,
            'categorySubtitle': this.state.categorySubtitle,
        })
    }

    setCategoryStates = (categoryTitle, categorySubtitle) => {
        this.setState({
            categoryTitle: categoryTitle,
            categorySubtitle: categorySubtitle,
        })
        this.pushToCategoryArray();
    }

    render() {
        return (
            <CategoryComponent
                setCategoryStates={this.setCategoryStates}
                categoryTitle={'Category Title Text'}
                categorySubtitle={'Category Subtitle Text'}
            />
        );
    }
}

class CategoryComponent extends Component {
    render() {
        var categoryTitle = this.props.categoryTitle;
        var categorySubtitle = this.props.categorySubtitle;
        return (
            <div onClick={() => (this.props.setCategoryStates(
                    categoryTitle,
                    categorySubtitle,
                ))}
            >
                <h1>{categoryTitle}</h1>
                <h2>{categorySubtitle}</h2>
            </div>
        );
    }
}

我可以在控制台中看到要获取的categoryTitlecategorySubtitle,但是它们被作为null推送到this.state.categoryArray中。这是我需要使用诺言的情况吗?采取另一种方法?

2 个答案:

答案 0 :(得分:0)

我认为React不会重新渲染,因为pushToCategoryArray直接更改了状态。需要在this.setState函数中分配新的数组。

// this.state.categoryArray.push({...})

const prevCategoryArray = this.state.categoryArray
this.setState({
    categoryArray: [ newObject, ...prevCategoryArray],        
)}    

答案 1 :(得分:0)

发生这种情况是因为setState是异步(https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly)。

问题出在这里

    //State has categoryTitle as null and categorySubtitle as null.
    this.state = {
        categoryTitle: null,
        categorySubtitle: null,
        categoryArray: [],
    }

//This gets the correct values in the parameters
setCategoryStates = (categoryTitle, categorySubtitle) => {
    //This is correct, you're setting state BUT this is not sync
    this.setState({
        categoryTitle: categoryTitle,
        categorySubtitle: categorySubtitle,
    })
    this.pushToCategoryArray();
}

//This method is using the state, which as can be seen from the constructor is null and hence you're pushing null into your array.
pushToCategoryArray = () => {
    this.state.categoryArray.push({
        'categoryTitle': this.state.categoryTitle,
        'categorySubtitle': this.state.categorySubtitle,
    })
}

解决方案:将回调传递给setState

setCategoryStates = (categoryTitle, categorySubtitle) => {
    //This is correct, you're setting state BUT this is not sync
    this.setState({
        categoryTitle: categoryTitle,
        categorySubtitle: categorySubtitle,
    }, () => {
       /*
          Add state to the array
          This callback will be called once the async state update has succeeded
          So accessing state in this variable will be correct.
       */
       this.pushToCategoryArray()
    })
}

并更改

pushToCategoryArray = () => {
    //You don't need state, you can simply make these regular JavaScript variables
    this.categoryArray.push({
        'categoryTitle': this.state.categoryTitle,
        'categorySubtitle': this.state.categorySubtitle,
    })
}