简体   繁体   English

使用反应 select 多个更新 state 的正确方法

[英]Correct way to update state with react select multiple

I've added react-select package for my app.我为我的应用添加了 react-select package。 And I want to create new values in the select option with CreatableMulti component and push newly created values to my state array.我想使用CreatableMulti组件在 select 选项中创建新值,并将新创建的值推送到我的 state 数组中。

The trouble I'm having is the first typed element is not pushed into the state array.我遇到的问题是第一个类型的元素没有被推入 state 数组。 It is pushed to state on 2nd time.第二次推送到 state。 On the 3rd time the first element is pushed twice.第三次第一个元素被推送两次。

I've created a replica of code in the codesandbox: https://codesandbox.io/s/react-codesandboxer-example-el0ps?file=/example.js:164-178我在代码盒中创建了代码副本: https://codesandbox.io/s/react-codesandboxer-example-el0ps?file=/example.js:164-178

And how do I connect X sign with state to remove elements from array.以及如何将X符号与 state 连接以从数组中删除元素。 If I click X the copy of whole array is pushed into the array.如果我单击X ,整个数组的副本将被推入数组。

React for enhancing performance sometimes batches this.setState() calls instead of executing them one at a time which could result in unexpected behaviour.用于提高性能的 React 有时会批处理 this.setState() 调用,而不是一次执行一个调用,这可能会导致意外行为。 Instead try to merge newValues to state after you have manipulated your data through map.通过 map 操作数据后,尝试将 newValues 合并到 state。

Something like this:像这样的东西:

const newValuesArr = newValue.map(item => item.value);
this.setState({ values: newValuesArr });

For more in-depth explanation, please refer to this link: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous更深入的解释请参考这个链接: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

Please run the following code and let me know if it solves your problem.请运行以下代码,如果它解决了您的问题,请告诉我。

import React, { Component } from "react";

import CreatableSelect from "react-select/creatable";
import { colourOptions } from "./docs/data";

export default class CreatableMulti extends Component<*, State> {
  state = {
    values: []
  };
  handleChange = (newValue: any, actionMeta: any) => {
    const newValuesArr = newValue ? newValue.map(item => item.value) : [];
    this.setState({ values: newValuesArr });
  };
  render() {
    return (
      <CreatableSelect
        isMulti
        onChange={this.handleChange}
        options={colourOptions}
      />
    );
  }
}

According to the docs根据文档

setState() does not always immediately update the component . setState()并不总是立即更新组件 It may batch or defer the update until later.它可能会批量更新或将更新推迟到以后。 This makes reading this.state right after calling setState() a potential pitfall.这使得在调用setState()之后立即阅读this.state是一个潜在的陷阱。 Instead, use componentDidUpdate or a setState callback ( setState(updater, callback) ), either of which are guaranteed to fire after the update has been applied.相反,请使用componentDidUpdatesetState回调 ( setState(updater, callback) ),它们都保证在应用更新后触发。 If you need to set the state based on the previous state, read about the updater argument below.如果您需要在之前的 state 的基础上设置 state,请阅读下面的updater参数。

So you could achive what you want in your case like below所以你可以在你的情况下实现你想要的,如下所示

import React, { Component } from "react";

import CreatableSelect from "react-select/creatable";
import { colourOptions } from "./docs/data";

export default class CreatableMulti extends Component<*, State> {
  state = {
    values: []
  };
  handleChange = (newValue: any, actionMeta: any) => {
    const newValuesArr = newValue ? newValue.map(item => item.value) : [];
    this.setState({ values: newValuesArr }, () => {
      console.log(this.state.values);
    });
  };
  render() {
    return (
      <CreatableSelect
        isMulti
        onChange={this.handleChange}
        options={colourOptions}
      />
    );
  }
}

Here is the codesandbox link这是codeandbox链接

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

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