为什么在指定值为空时反应突出显示我的第二个<select>选项?

时间:2016-12-18 10:10:32

标签: reactjs

我有2&lt; select&gt;如下面的代码所示: &#13; &#13; 功能FirstSelect(道具){&#13;   const list = props.list.map(item =&gt; {&#13;     返回&lt; option key = {item.id} value = {item.id}&gt; {item.text}&lt; / option&gt;&#13;   })&#13;   返回&lt; select size =&#39; 8&#39;的onChange = {props.onChange}&GT; {列表}&LT; /选择&GT;&#13; }&#13; &#13; 功能SecondSelect(道具){&#13;   的console.log(props.value)&#13;   const list = props.list.map(item =&gt; {&#13;     返回&lt; option key = {item.id} value = {item.id}&gt; {item.text}&lt; / option&gt;&#13;   })&#13;   返回&lt; select size =&#39; 8&#39; onChange = {props.onChange} value = {props.value}&gt; {list}&lt; / select&gt;&#13; }&#13; &#13; class TwoSelect扩展了React.Component {&#13;   constructor(){&#13;     超级()&#13;     this.state = {&#13;       firstList:[&#13;         {id:&#39; fitem1&#39;,text:&#39; fvalue1&#39;},&#13;         {id:&#39; fitem2&#39;,text:&#39; fvalue2&#39;}&#13;       ]&#13;       secondList:[&#13;         {id:&#39; sitem1&#39;,text:&#39; svalue1&#39;},&#13;         {id:&#39; sitem2&#39;,text:&#39; svalue2&#39;}&#13;       ]&#13;       selectedValue1:&#39;&#39;,&#13;       selectedValue2:&#39;&#39;&#13;     }&#13;   }&#13; &#13;   render(){&#13;     返回&lt; div&gt;&#13;       &lt; FirstSelect list = {this.state.firstList} onChange = {(e)=&gt; {this.firstListSelectionChanged(e.target.value)}} /&gt;&#13;       &lt; div&gt; selectedValue1:{this.state.selectedValue1}&lt; / div&gt;&#13;       &lt; SecondSelect list = {this.state.secondList} value = {this.state.selectedValue2} onChange = {(e)=&gt; {this.secondListSelectionChanged(e.target.value)}} /&gt;&#13;       &lt; div&gt; selectedValue2:{this.state.selectedValue2}&lt; / div&gt;&#13;     &LT; / DIV&GT;&#13;   }&#13; &#13;   firstListSelectionChanged(value){&#13;     this.setState({&#13;       selectedValue1:value&#13;     })&#13;   }&#13; &#13;   secondListSelectionChanged(value){&#13;     this.setState({&#13;       selectedValue2:value&#13;     })&#13;   }&#13; &#13; }&#13; &#13; ReactDOM.render(&#13;   &lt; TwoSelect /&gt;,&#13;   的document.getElementById(&#39;根&#39;)&#13; );&#13; &lt; script src =&#34; https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"&gt;&lt; / script&gt;&#13; &lt; script src =&#34; https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"&gt;&lt; / script&gt;&#13; &lt; div id =&#34; root&#34;&gt;&lt; / div&gt;&#13; &#13; &#13; 首次渲染时,没有什么是奇怪的。但是当我在第一个&lt; select&gt;中选择一个项目时,React会突出显示第二个&lt; select&gt;中的第一个项目,而不会触发onChange事件,而且selectedValue2仍然是一个空字符串。因此,点击第二个&lt; select&gt;的第一项。没有触发它的onChange事件。 (单击第二个项目,然后单击第一个项目正常工作) 我期望的是第二个&lt; select&gt;当属性值为空时,不会突出显示任何项目! 我试着用 this.state = {   selectedValue1:null,   selectedValue2:null } 它的工作方式与我预期的一样,但React一直建议使用空字符串而不是null! 我的代码出了什么问题?

1 个答案:

答案 0 :(得分:2)

你的主要问题是它不应该为空,但正如React建议的那样,它应该是未定义的或空字符串。

null不是可接受的值的原因是因为属性只允许字符串值,而没有对象。由于null是一个对象,因此不建议使用它。然而,未定义不会添加属性(因为它未定义)。

可以在sourcecode中找到这样的原因。当select不是多值时,默认情况下,当值未定义时,第一个选项将获得selected。给定值时,它必须是可字符串的,您可以在代码here的注释部分找到

如果该值设置为undefined,则不会抱怨,正如您在此代码段中所看到的那样

&#13;
&#13;
class CustomList extends React.Component {
	render() {
    var selectedId = this.props.selectedValue;
  	return (
    	<select size="8" onChange={this.props.onChange} value={selectedId}>
      	{ this.props.items.map( item => <option key={item.id} value={item.id}>{item.text}</option> ) }
      </select>
    );
  }
}

class TwoSelect extends React.Component {
  constructor() {
    super()
    this.state = {
      firstList: [
        {id: 'fitem1', text: 'fvalue1'},
        {id: 'fitem2', text: 'fvalue2'}
      ],
      secondList: [
        {id: 'sitem1', text: 'svalue1'},
        {id: 'sitem2', text: 'svalue2'}
      ],
      selectedValue1: undefined,
      selectedValue2: undefined
    }
  }

  render() {
    return <div>
      <CustomList placeholder="select" items={this.state.firstList} selectedValue={this.state.selectedValue1} onChange={(e)=>{this.selectionChanged('selectedValue1', e.target.value)}} />
      <div>selectedValue1: {this.state.selectedValue1}</div>
      <CustomList placeholder="" items={this.state.secondList} selectedValue={this.state.selectedValue2} onChange={(e)=>{this.selectionChanged('selectedValue2', e.target.value)}} />
      <div>selectedValue2: {this.state.selectedValue2}</div>
    </div>
  }

  selectionChanged(stateKey, value) {
    this.setState({
      [stateKey]: value
    });
  }
}


ReactDOM.render(
  <TwoSelect />,
  document.getElementById('container')
);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>
&#13;
&#13;
&#13;

对于一些额外的建议,没有理由让你制作完全相同的多个列表组件。这将使您的应用程序在未来非常复杂,您真的不需要这种复杂性。

尝试查看代码中可以重用的内容,然后只使用那些单个组件。

例如,您的FirstListSecondList组件可以简化为例如CustomList,然后您只需要在CustomList中拨打TwoSelect两次渲染方法。

class CustomList extends React.Component {
  render() {
    var selectedId = this.props.selectedValue;
    return (
      <select onChange={this.props.onChange} value={selectedId}>
        { this.props.items.map( item => <option key={item.id} value={item.id}>{item.text}</option> ) }
      </select>
    );
  }
}

创建select框时,大多数情况下选择了默认值,为了避免这种情况,您可以选择添加一个额外的空选项,在这种情况下会选择此选项。

如果我现在要呈现您的TwoSelect组件,我可以更改以下内容以使您的应用程序在将来更容易维护(比如稍后会添加第三个列表; - )

  render() {
    return <div>
      <CustomList 
        placeholder="select" 
        items={this.state.firstList} 
        selectedValue={this.state.selectedValue1}
        onChange={(e)=>{this.selectionChanged('selectedValue1', e.target.value)}} />
      <div>selectedValue1: {this.state.selectedValue1}</div>
      <CustomList 
        placeholder="" 
        items={this.state.secondList} 
        selectedValue={this.state.selectedValue2} 
        onChange={(e)=>{this.selectionChanged('selectedValue2', e.target.value)}} />
      <div>selectedValue2: {this.state.selectedValue2}</div>
    </div>;
  }

正如您所看到的,我删除了对2个处理程序的需求,现在您的选择更改了事件而不是这样:

selectionChanged(stateKey, value) {
  this.setState({
    [stateKey]: value
  })
}

这会使stateKey成为一个字符串值,如'selectedValue1',正如您从上面的处理程序中的变化中看到的那样

使用jsfiddle的演示可以找到here