无法将自定义Select值传播到其父组件状态

时间:2019-04-25 05:14:58

标签: javascript reactjs redux jsx

我有一个基本的ReactJS应用,其中包含一个自定义Select,该应用会在2秒后填充。

./ src / controls / Select / Select.js

import React, { Component } from 'react';
import './Select.scss';

class Select extends Component {

  constructor(props) {
    super(props);
    let { name, value, data, className, onChange, onFocus, onBlur, ...controlProps } = this.props;
    this.name = name;
    this.onChange = onChange || ((e) => { });
    this.onFocus = onFocus || ((e) => { });
    this.onBlur = onBlur || ((e) => { });
    this.controlProps = controlProps;
    this.state = {
      [name]: value,
      className,
    };
  }

  componentDidMount() {
    this.handleChange({ target: this.refs.select });
  }

  handleChange = (e) => {
    let target = e.target;
    let name = target.name;
    let value = target.value;
    this.setState({
      [name]: value,
    });
    this.onChange(e);
  };

  render() {
    let data = this.props.data || [];
    return (
      <div className="control-select" {...this.controlProps}>
        <div className="custom-dropdown custom-dropdown--grey">
          <select
            ref="select"
            name={this.name}
            className="custom-dropdown__select custom-dropdown__select--grey"
            value={this.state[this.name]}
            onChange={this.handleChange}
          >
            {
              data.map((elem, index) => {
                return <option value={elem.value} key={index}>{elem.text}</option>
              })
            }
          </select>
        </div>
      </div>
    );
  }

}

export default Select;

我也有主要的App

./ src / index.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Select from './controls/Select/Select';
import './styles.scss';

export default class Lab extends Component {

    constructor(props) {
    super(props);
    this.state = {
      selection: '',
      options: [],
    }
    setTimeout(() => {
      this.setState({
        options: [
          { "value": "option_01", "text": "Option 01" },
          { "value": "option_02", "text": "Option 02" },
          { "value": "option_03", "text": "Option 03" },
          { "value": "option_04", "text": "Option 04" },
          { "value": "option_05", "text": "Option 05" },
        ],
      });
    }, 2000);
  }

  handleChange = (e) => {
    let target = e.target;
    let name = target.name;
    let value = target.value;
    this.setState({
      [name]: value,
    });
  };

    render() {
        return (
            <div className="App">
        <div style={{ borderBottom: '1px solid #ddd', margin: '20px 0 10px 0' }}>
          The value on the select box should appear on the yellow box automatically.
        </div>
                {/* BEGIN OF WORKING AREA */}
        <table style={{ display: 'inline-block', margin: '0 0 10px', border: 'none' }}>
          <tbody>
            <tr>
              <td style={{ width: '218px', border: 'none' }}>
                <Select
                  name="selection"
                  value={this.state.selection}
                  data={ this.state.options.map(elem => { return { value: elem.value, text: elem.text }; }) }
                  style={{ width: '100%' }}
                  onChange={ this.handleChange }
                />
              </td>
              <td style={{ width: '100px', border: 'none', color: '#b00', backgroundColor: '#ffa', textAlign: 'center', fontSize: '14px' }}>
                <span>{this.state.selection}</span>
              </td>
            </tr>
          </tbody>
        </table>
        {/* END OF WORKING AREA */}
            </div>
        );
    }
}

if (document.getElementById('root')) {
    ReactDOM.render(<Lab />, document.getElementById('root'));
}

我需要的是,它是在填充自定义Select之后,它将其值传播到父组件state。现在,当它填充时,它不会执行此操作(您可以使用空白的黄色框进行检查)。另一方面,如果更改该Select上的选项,则其值将成功传播。

在这里,您可以使用它的Codesandbox.io

https://codesandbox.io/s/73z220z11q

如果可能,请提供您的解决方案的分叉式Codesandbox.io

这就是我要发生的事情:

enter image description here

[更新]

这里有我关注的真实代码:

https://codesandbox.io/s/xl6zxz0v84

如果用户在Select上手动选择一个选项,则该值将正确设置为selectedTheme(在App状态下)。那部分很好。

我想要的是如果用户没有手动选择任何内容,则选择项上显示的值应设置为selectedTheme。当前未设置任何内容(如果用户不进行交互)。

您可以通过单击selectedTheme按钮来检查Submit的值。

谢谢!

2 个答案:

答案 0 :(得分:0)

我认为问题在于您如何直接从自定义选择的handleChange调用componentDidMount当时,您的target确实没有value的原因是您要根据Redux状态设置选项。

要解决此问题,可以在要从componentWillReceiveProps获取选项的组件中使用Redux,并在获取更新时手动更改state.selection。像这样:

componentWillReceiveProps(nextProps) {
  if (this.props.options.length !== nextProps.options.length) {
    this.setState({ selection: nextProps.options[0].value });
  }
}

这里是forked+updated sandbox

答案 1 :(得分:0)

嗨,错误是选择元素仅在触发onChange函数时才设置选择。

如果需要,在填充时需要手动设置或在选择状态下设置默认值。

 //set the selection default state at the time of setting options in constructor.
 constructor(props) {
    super(props);
    this.state = {
      selection: "",
      options: []
    };
    setTimeout(() => {
      this.setState(
        {
          options: [
            { value: "option_01", text: "Option 01" },
            { value: "option_02", text: "Option 02" },
            { value: "option_03", text: "Option 03" },
            { value: "option_04", text: "Option 04" },
            { value: "option_05", text: "Option 05" }
          ]
        },
        () => this.setState({ selection: this.state.options[0].value })
      );
    }, 2000);
  }

Demo link