Как сделать выпадающий список контролируемым компонентом? - PullRequest
0 голосов
/ 05 марта 2020

Я пытаюсь создать управляемый раскрывающийся компонент, указав value в качестве свойства. Следовательно, если раскрывающийся список называется, например: <DropdownList title="Select Options" list={options} value={3}/>, он выберет третье значение по умолчанию и не будет изменяться.

Я создал функцию handleValue для реализации вышеуказанной задачи.

handleValue(list) {
    if (this.state.value) {
      const newValue = Number(this.state.value);

      const optionHasValue = list.find(item => item.id === newValue);

      this.setState(
        {
          headerTitle: optionHasValue.title,
          listOpen: false,
        },
        this.resetThenSet(optionHasValue.id, optionHasValue.stateKey)
      );
    }
  }

Однако не уверен, правильно ли это и как включить его в рендер. Цените любое решение, чтобы это работало!

class DropdownList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      listOpen: false,
      headerTitle: this.props.title,
      value: this.props.value,
    };
    this.close = this.close.bind(this);
  }

  componentDidUpdate() {
    const { listOpen } = this.state;
    setTimeout(() => {
      if (listOpen) {
        window.addEventListener('click', this.close);
      } else {
        window.removeEventListener('click', this.close);
      }
    }, 0);
  }

  componentWillUnmount() {
    window.removeEventListener('click', this.close);
  }

  close() {
    this.setState({
      listOpen: false,
    });
  }

  resetThenSet(id, key) {
    const temp = this.props.list;
    temp.forEach(item => (item.selected = false));
    temp[id].selected = true;
    this.setState({
      [key]: temp,
    });
  }

  selectItem(title, id, stateKey) {
    this.setState(
      {
        headerTitle: title,
        listOpen: false,
      },
      this.resetThenSet(id, stateKey)
    );
  }

  toggleList() {
    this.setState(prevState => ({
      listOpen: !prevState.listOpen,
    }));
  }

  handleValue(list) {
    if (this.state.value) {
      const newValue = Number(this.state.value);

      const optionHasValue = list.find(item => item.id === newValue);

      this.setState(
        {
          headerTitle: optionHasValue.title,
          listOpen: false,
        },
        this.resetThenSet(optionHasValue.id, optionHasValue.stateKey)
      );
    }
  }

  render() {
    const { list, disabled } = this.props;
    const { listOpen, headerTitle } = this.state;

    let menuItems;

    if (!list) {
      menuItems = <DropdownItem>Empty</DropdownItem>;
    } else {
      menuItems = list.map(item => (
        <DropdownItem
          key={item.id}
          onClick={() => this.selectItem(item.title, item.id, item.key)}
        >
          {item.title} {item.selected && <GreenCheckIcon />}
        </DropdownItem>
      ));
    }

    return (
      <Wrapper onLoad={this.handleValue}>
        <Header
          onClick={() => {
            this.toggleList();
          }}
          disabled={disabled}
        >
          <HeaderTitle>{headerTitle}</HeaderTitle>
          <SortIcon />
        </Header>
        {listOpen && (
          <DropdownMenu onClick={e => e.stopPropagation()}>
            {menuItems}
          </DropdownMenu>
        )}
      </Wrapper>
    );
  }
}
...