React Bootstrap select 选项在更新列表时呈现并且不显示第一个可用选项

React Bootstrap select option renders and does not display first available option when list renewed

项目使用ReactBootstraphttps://react-bootstrap.github.io/
该应用程序从 api 接收存储桶列表。有两个 select 下拉菜单。这里的objective是同一个bucket不能在两个select中都被selected。因此,如果第一个 select 包含 "Red" 个存储桶 select,则第二个下拉列表的列表中不能包含 "Red"。 我已经实现了第二个列表的创建和状态的正确更新。但是,当第二个下拉列表重新呈现时,在某些情况下,它会显示错误的条目 selected.

步骤:

  1. 初始负载:

第一个列表[红、绿、蓝]。已选择:红色。 第二个列表[绿色,蓝色]。已选择:绿色

  1. 在第一个下拉列表中 select 绿色:

第二个列表[红色,蓝色]。但是 selected 选项是蓝色的。它应该是红色的,因为它是列表中第一个可用的。

我知道这可能是因为 Red 之前不在第二个下拉列表中。但这不重要吗?看到列表更新了,组件重新渲染了

import React, { Component } from "react";
import Form from "react-bootstrap/Form";
import ToBucket from "./toBucket";

class Buckets extends Component {
  constructor(props) {
    super(props);
    this.state = {
      fromBucketList: [],
      toBucketList: [],
      selectedFromBucket: [],
      selectedToBucket: [],
    };
  }

  handleFromBucketChange = (event) => {
    let nam = event.target.name;
    let bucketId = event.target.value;
    const selectedFromBucket = this.getBucketById(bucketId);
    let rebuiltToBucketList = [...this.state.fromBucketList];
    let selectedFromBucketIndex = rebuiltToBucketList.indexOf(
      selectedFromBucket
    );
    rebuiltToBucketList.splice(selectedFromBucketIndex, 1);
    this.setState({ toBucketList: rebuiltToBucketList });
    this.setState({ [nam]: selectedFromBucket });
    this.setState({ selectedToBucket: rebuiltToBucketList[0] });
  };

  handleToBucketChange = (event) => {
    let nam = event.target.name;
    let bucketId = event.target.value;
    const selectedToBucket = this.getBucketById(bucketId);
    this.setState({ [nam]: selectedToBucket });
  };

  componentDidMount() {
    const buckets = [
      { id: 1, color: "red" },
      { id: 2, color: "green" },
      { id: 3, color: "blue" },
    ];

    let initialToBucketList = [...buckets];
    initialToBucketList.splice(0, 1);

    this.setState({ fromBucketList: buckets });
    this.setState({ toBucketList: initialToBucketList });
    this.setState({ selectedFromBucket: buckets[0] });
    this.setState({ selectedToBucket: initialToBucketList[0] });
  }

  getBucketById = (id) => {
    let foundedBucket = this.state.fromBucketList.find(
      (element) => element.id == id
    );
    return foundedBucket;
  };

  render() {
    return (
      <React.Fragment>
        <Form noValidate validated={this.state.validated}>
          <Form.Group controlId="SelectFromBucket">
            <Form.Label>Select FROM bucket:</Form.Label>
            <Form.Control
              required
              type="text"
              as="select"
              onChange={this.handleFromBucketChange}
              name="selectedFromBucket"
            >
              {this.state.fromBucketList.map((bucket) => (
                <option key={bucket.id} value={bucket.id}>
                  {bucket.color}
                </option>
              ))}
            </Form.Control>
          </Form.Group>
          <React.Fragment>
            <ToBucket
              handleToBucketChange={this.handleToBucketChange}
              toBucketList={this.state.toBucketList}
            />
          </React.Fragment>
          <p>
            From :{this.state.selectedFromBucket.color}
            <br></br>
            To :{this.state.selectedToBucket.color}
          </p>
        </Form>
      </React.Fragment>
    );
  }
}

export default Buckets;

第二个下拉菜单:

import React, { Component } from "react";
import Form from "react-bootstrap/Form";

class ToBucket extends Component {
  render() {
    return (
      <React.Fragment>
        <Form.Group controlId="SelectToBucket">
          <Form.Label>Select TO bucket:</Form.Label>
          <Form.Control
            required
            type="text"
            as="select"
            onChange={this.props.handleToBucketChange}
            name="selectedToBucket"
          >
            {this.props.toBucketList.map((bucket) => (
              <option key={bucket.id} value={bucket.id}>
                {bucket.color}
              </option>
            ))}
          </Form.Control>
        </Form.Group>
      </React.Fragment>
    );
  }
}

export default ToBucket;

我希望答案不是此代码的解决方法或 hack,而是如果此方法不正确,则可以作为另一个方向的概念指南。

第二个下拉列表的 FormControl 可能不会更改其值,因为没有传递给它的值道具。

尝试将所选值作为 props 从第一个桶传递到第二个桶

我从不使用 react-bootstrap 但这段代码应该有效。

第一个组件

<ToBucket
   value={this.state.selectedToBucket && this.state.selectedToBucket.id}
   handleToBucketChange={this.handleToBucketChange}
   toBucketList={this.state.toBucketList}
/>

第二个组件

import React, { Component } from "react";
import Form from "react-bootstrap/Form";

class ToBucket extends Component {
  render() {
    return (
      <React.Fragment>
        <Form.Group controlId="SelectToBucket">
          <Form.Label>Select TO bucket:</Form.Label>
          <Form.Control
            required
            value={this.props.value}
            type="text"
            as="select"
            onChange={this.props.handleToBucketChange}
            name="selectedToBucket"
          >
            {this.props.toBucketList.map((bucket) => (
              <option key={bucket.id} value={bucket.id}>
                {bucket.color}
              </option>
            ))}
          </Form.Control>
        </Form.Group>
      </React.Fragment>
    );
  }
}

export default ToBucket;