首页 > 解决方案 > (反应)侦听由作为道具传播的更改数据列表触发的下拉/选择值更改

问题描述

我正在使用一个简单的 HTML 选择下拉菜单并使用反应(==> 受控组件)控制它。到目前为止一切都很好。问题是 - 选择选项每隔几秒钟通过异步 ajax 调用更新一次,并且在开始时为空。选择数据列表通过道具传播。

因此,选择数据列表发生了变化,选择的选项列表发生了变化——但没有触发任何变化(afaik 的反应设计)。我找到了一种工作方式来监听这些更改,方法是监听“componentDidUpdate”并通过读出 select 的值作为参考“手动”触发 onChange - 但这似乎非常“un react-ish”(下面的代码) . 有谁知道“反应”的方式来做到这一点?

完整代码:

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

标签: javascriptreactjsbrowser

解决方案


您应该将道具传递给状态。

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>
    );
  }

监听器的 props 变化:

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

试试这个代码框https://codesandbox.io/s/pjky3r4z60


推荐阅读