使用select和onChange处理程序

时间:2017-01-05 12:12:05

标签: javascript reactjs

我制作了一个通过xhr加载数据的组件,用户选择< select>的值元件。

class SomeComponent extends Component {
    state = {
        data: [],
        currentCategory: 'all'
    }
    switchCategory = (ev) => {
        console.log('Selected category is ' + ev.target.value);

        this.setState({
            currentCategory: ev.target.value
        });

        this.loadData();
    }
    loadData = async () => {
        let { currentCategory } = this.state;

        // Always print previous value!!!
        console.log(currentCategory);

        // Get data via XHR...
    }
    render() {
        return (
            <div>
                <select value={currentCategory} onChange={this.switchCategory}>
                    <option value="all">All</option>
                    {categories.map( category => 
                    <option key={category._id} value={category.category}>{category.display}</option>    
                    )}
                </select>

                <table>
                    // ... prints data with this.state.data
                </table>
            </div>
        );
    }
}

上面的代码只是简单的说明。代码非常简单,我只是将select元素的值与this.state.currentCategory同步,并使用该类的switchCategory方法检测它的切换。

但主要的问题是当我访问组件的状态时,它总是包含先前的值,而不是当前的值。您可以看到我在选择更改的值上更新currentCategory。

    switchCategory = (ev) => {
        console.log('Selected category is ' + ev.target.value);

        this.setState({
            currentCategory: ev.target.value
        });

        this.loadData();
    }

所以在这种情况下,this.state.currentCategory必须没有“all”,就像其他“Apple”一样,但它仍然包含“all”,而不是“Apple”!

    loadData = async () => {
        let { currentCategory } = this.state;

        // Always print previous value!!! I expected "Apple", but it has "all"
        console.log(currentCategory);

        // Get data via XHR...
    }

所以最终XHR发生了以前的值,它给了我错误的数据,这是我没想到的。 之后,选择其他值的选择(让我们称之为香蕉),它有一个苹果,而不是香蕉!

我知道setState是“sync”作业,因此在更新状态后调用this.switchCategory会发生,因此它必须具有当前值,而不是之前的值。

但是当我在控制台中打印组件的状态时,它不是。

那么,我错过了什么?为什么我总是得到旧数据,不存在?如果我采取了错误的做法,那么我可以做些什么选择呢?

任何建议都会非常感激。谢谢!

1 个答案:

答案 0 :(得分:2)

这里的问题是setState是异步的(在某些情况下可以同步)。这就是为什么你得到以前的价值。

有两种可能的解决方案。

//
// 1. use value directly.
//
switchCategory = (ev) => {
    this.setState({ currentCategory: ev.target.value });
    this.loadData(ev.target.value);
}

loadData = async (currentCategory) => {
    console.log(currentCategory);

    // Get data via XHR...
}

//
// 2. use completition callback on `setState`.
//
switchCategory = (ev) => {
    this.setState({ currentCategory: ev.target.value }, () => {
        this.loadData(ev.target.value);
    });
}

loadData = async () => {
    const { currentCategory } = this.state;
    console.log(currentCategory);

    // Get data via XHR...
}

关于React [link]

中同步setState的文章