组件重新呈现时,构造函数中创建的元素未更新

时间:2018-02-24 21:03:33

标签: javascript reactjs constructor ecmascript-6

为什么我在构造函数中创建的<select>在我选择其他风味时未更新?另一个select以及文本已更新。

&#13;
&#13;
class ConstructorComponent extends React.Component {
  constructor() {
    super();
    
    this.state = {
      icecream: 'vanilla',
    };
    
    this.select = (
      <select
        value={this.state.icecream}
        onChange={this.onChange}
      >
        <option value="chocolate">Chocolate</option>
        <option value="vanilla">Vanilla</option>
        <option value="strawberry">Strawberry</option>
      </select>
    );
  }
  
  onChange = event => {
    this.setState({
      icecream: event.target.value,
    });
  };
    
  render() {
    return (
      <div>
        Icecream flavor: {this.state.icecream}
        <br />
        {this.select}
        <br />
        <select
          value={this.state.icecream}
          onChange={this.onChange}
        >
          <option value="chocolate">Chocolate</option>
          <option value="vanilla">Vanilla</option>
          <option value="strawberry">Strawberry</option>
        </select>
      </div>
    );
  }
}

ReactDOM.render(
  <ConstructorComponent />,
  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;

我通过在this.select中克隆render()就是这样做的:{React.cloneElement(this.select, {value: this.state.icecream})}

但是,正如我的问题的几个答案所建议的那样,使this.select成为一种方法可能更好。我会看到最适合我的实际代码的内容,而不只是这个愚蠢的例子:)

3 个答案:

答案 0 :(得分:2)

因为第一次选择中的this.state.icecream只被解释一次,所以在构造函数中定义this.select时。因此,当您的ConstructorComponent状态发生变化时第二次重新呈现时,您的第一次选择中无需更新。

您需要将this.select定义为返回<select>的函数,如下所示:

this.select = () => {
  return (
    <select
      value={this.state.icecream}
      onChange={this.onChange}
    >
      <option value="chocolate">Chocolate</option>
      <option value="vanilla">Vanilla</option>
      <option value="strawberry">Strawberry</option>
    </select>
  )
}

并在渲染中调用this.select()

您还可以使用道具<select> 创建对渲染中ref的引用:

render() {
  <select
    value={this.state.icecream}
    onChange={this.onChange}
    ref={select => (this.select = select)}  // the magic happens here
  >
    <option value="chocolate">Chocolate</option>
    <option value="vanilla">Vanilla</option>
    <option value="strawberry">Strawberry</option>
  </select>
}

这样做,您不需要将this.select定义为构造函数中的函数。

答案 1 :(得分:1)

第一个选择不起作用,因为它只在构造函数中渲染一次。第二个选择有效,因为每次应用程序状态更新时它都会重新呈现。

如果有帮助,请不要将JSX元素视为实际HTML元素的“实例”。将它们视为您希望应用程序与您的州相关的简单方式。如果我的状态是“a”,那么我用“a”渲染一个select,如果我的状态是“b”,那么我用“b”渲染一个select,依此类推。

答案 2 :(得分:1)

页面上的第一个选择框仅在只调用一次的构造函数中呈现,因此组件将始终保持与首次呈现时相同。换句话说,它是静态的。每次更新组件时,将重新渲染第二个选择框。

为了修复代码,您可以将构造函数中的行更改为函数:

this.select = () => (
  <select
    value={this.state.icecream}
    onChange={this.onChange}
  >
    <option value="chocolate">Chocolate</option>
    <option value="vanilla">Vanilla</option>
    <option value="strawberry">Strawberry</option>
  </select>
);

然后更改你的return语句来调用这个函数:

<br />
  {this.select()}
<br />