(реагировать) Прослушивание раскрывающихся / выбранных изменений значений, вызванных измененным списком данных, распространяемым как реквизиты - PullRequest
0 голосов
/ 25 июня 2018

Я использую простой выпадающий список HTML и управляю им с помощью реагирования (==> контролируемый компонент).Пока все хорошо.Проблема в том, что опции выбора обновляются с помощью асинхронного вызова ajax каждые несколько секунд и в начале остаются пустыми.Список выбранных данных распространяется через реквизит.

Таким образом, список выбранных данных изменяется, список выбранных параметров изменяется, но никаких изменений не происходит (на самом деле, по замыслу реакции).Я нашел рабочий способ прослушать эти изменения, прослушав "componentDidUpdate" и запустив onChange "вручную", считав значение select как ссылку - но это выглядит очень "не реагирующим" (код ниже),Кто-нибудь знает, как «реагировать» способ сделать это?

Полный код:

class Dropdown extends React.Component {
    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.dropDown = React.createRef();      
    }

    handleChange(event) {
        if (this.props.onChange) this.props.onChange(event.target.value);
    }

    componentDidUpdate(prevProps) {
        if (this.props.options.length != prevProps.options.length) {
            if (this.props.onChange) this.props.onChange(this.dropDown.current.value);
        } else {
            for (let i = 0; i < this.props.options.length; i++) {
                if (this.props.options.value != prevProps.options.value) {
                    if (this.props.onChange) this.props.onChange(this.dropDown.current.value);
                    return;
                }
            }
        }
    }

    render() {
        const optionList = this.props.options.map(option => <option value={option.value} key={option.value}>{option.name}</option>);
        return <select value={this.props.value} onChange={this.handleChange} ref={this.dropDown}>{optionList}</select>;
    }
}

props.options начинаются как пустой список.Некоторые родительские узлы хранят этот список как состояние и обновляют его каждые несколько секунд с помощью запроса ajax.

Код песочницы: https://codesandbox.io/s/6l927kpx13

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

React обрабатывает свои обновления, просматривая реквизиты и состояние компонента. То, как вы реализовали это сейчас, в основном правильно, когда вы вызываете setState(), запускается повторный рендеринг. Тем не менее, событие onChange, которое вы ищете, происходит не всякий раз, когда ваши параметры динамически обновляются, но это событие запускается всякий раз, когда ваш пользователь выбирает другую опцию. Это не имеет ничего общего с React.

См. Ответ, предоставленный Rizal Ibnu, если вы хотите более эффективно проверять наличие обновлений.

Однако я бы добавил некоторые обновления в ваш код, он может быть короче:

class Dropdown extends React.Component {
    constructor(props) {
        super(props);
    }

    // You can 'bind' this also with an arrow function
    handleChange = event => {
        if (this.props.onChange) this.props.onChange(event.target.value);
    };

    componentDidUpdate(prevProps) {
        if (this.props.options.length != prevProps.options.length) {
            if (this.props.onChange) this.props.onChange(this.dropDown.current.value);
        } else {
                this.props.options.forEach(() => {
                    if (this.props.options.value != prevProps.options.value) {
                        if (this.props.onChange)
                            this.props.onChange(this.dropDown.current.value);
                        return;
                    }
                })
            }
        }
    }

    render() {
        return (
            <select
                value={this.props.value}
                onChange={this.handleChange}
                // Consider using callback refs
                ref={dropdown => (this.dropDown = dropDown)}
            >
                // Pure preference, I like mapping a list inline
                {this.props.options.map(option => (
                    <option value={option.value} key={option.value}>
                        {option.name}
                    </option>
                ))}
            </select>
        );
    }
}

Я бы снова посмотрел на метод this.props.onChange от твоего родителя, я не думаю, что он должен быть неопределенным.

0 голосов
/ 25 июня 2018

Вы должны передать реквизиты в состояние.

state = {
    options: this.props.options,
}

метод рендеринга:

render() {
    const optionList = this.state.options.map((option, index) => (
      <option key={index} value={option.price}>{option.price}</option>
    ));

    return (
      <select>{optionList}</select>
    );
  }

слушатель изменений реквизита:

componentDidUpdate(prevProps) {
    if (this.props.options[0].price !== prevProps.options[0].price) {
      this.setState({
        options: this.props.options,
      });
    }
  }

Попробуйте этот код и окно https://codesandbox.io/s/pjky3r4z60

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...