Обновление выбранного элемента в приложениях JavaScript с неизменяемым состоянием

Допустим, у меня есть приложение JavaScript / HTML, которое

  • Управляет предметами
  • Имеет представление о выбранном предмете
  • Получает обновления элементов в реальном времени по мере выполнения приложения.

Если я хочу, чтобы мое приложение использовало неизменяемое состояние (immutable.js, redux, react и т. Д.), Концептуально, как мне синхронизировать обновления элемента в списке с выбранным элементом приложения, если они одинаковы?

Если я использую простые объекты / массивы JavaScript и мутацию, тогда выбранный элемент будет ссылкой на некоторый объект, а список элементов будет фактически списком ссылок на объекты элементов. Если я изменю свойство объекта в списке элементов, оно будет синхронизировано с выбранным элементом, потому что это тот же объект.

Как я смогу справиться с чем-то подобным, если я использую неизменяемое состояние? Если для выбранного элемента пришло обновление, нужно ли мне также не забывать возвращать новое состояние, в котором элемент в списке отличается, а к выбранному элементу применены те же преобразования?

Одна мысль состоит в том, чтобы иметь не выбранный элемент, а выбранный индекс, но когда я переупорядочиваю свой список элементов, должен ли я тогда не забывать возвращать новое состояние, в котором выбранный индекс отличается?

Есть ли шаблоны для работы с чем-то вроде этого?


person Drew LeSueur    schedule 12.11.2015    source источник


Ответы (1)


Вот один из способов, которым я это делаю. Вы можете изменить ссылку на index на item.id.

class JDropSelectRender extends React.Component {
  render() {
    let items = this.props.options.map((option) => {
      if (option.type == 'seperator') {
        return (<div style={DropdownSeperatorSty} key={option.key}></div>)
      } else {
        let selected = Boolean(option.label == this.state.selected.label);
        let labelSpanSty = {cursor: 'pointer'};
        labelSpanSty.color = selected ? 'green' : 'black';
        return (
          <div
            id='DropdownOptionSty'
            key={option.value}
            style={DropdownOptionSty}
            onMouseDown={this.setValue.bind(this, option)}
            onClick={this.setValue.bind(this, option)}
          >
            <span style={labelSpanSty}>{option.label}</span>
          </div>
        )
      }
    });

    let value = (<div style={placeSty}>{this.state.selected.label}</div>);
    let menu = this.state.isOpen ? <div style={DropdownMenuSty}>{items}</div> : null;

    return (
      <div id='DropdownSty' style={DropdownSty}>
        <div
          id='DropdownControlSty'
          style={DropdownControlSty}
          onMouseDown={this.handleMouseDown}
          onTouchEnd={this.handleMouseDown}
        >
          {value}
          <span id='DropdownArrowSty' style={DropdownArrowSty} />
        </div>
        {menu}
      </div>
    )
  }
}

export default class JDropSelect extends JDropSelectRender {
  constructor() {
    super();
    this.state = { isOpen: false, selected: {} };
  }
  componentWillMount() {
    this.setState({selected: this.props.defaultSelected || { label: 'Select...', value: '' }})
  }
  componentWillReceiveProps(newProps) {
    if (newProps.defaultSelected && newProps.defaultSelected !== this.state.selected) {
      this.setState({selected: newProps.defaultSelected});
    }
  }
  handleMouseDown = (event) => {
    if (event.type == 'mousedown' && event.button !== 0) return;
    event.stopPropagation();
    event.preventDefault();
    this.setState({ isOpen: !this.state.isOpen })
  }
  setValue = (option) => {
    if (option !== this.state.selected && this.props.onChange) this.props.onChange(this.props.itemName, option);
    this.setState({ selected: option, isOpen: false });
  }
}

person J. Mark Stevens    schedule 12.11.2015