在React中简化重复的代码

时间:2017-08-17 20:16:14

标签: javascript reactjs design-patterns

最好的做法是简化React中的以下内容吗?

getInitialState: function () {
  return {
    checkbox1: false,
    checkbox2: false,
    checkbox3: false,
    ...
  };
},

selectCheckbox1: function () {
  this.setState({
    checkbox1: !this.state.checkbox1
  });
},

selectCheckbox2: function () {
  this.setState({
    checkbox2: !this.state.checkbox2
  });
},

selectCheckbox3: function () {
  this.setState({
    checkbox3: !this.state.checkbox3
  });
},

...

render: function () {
  return (
    <div>
      <input type="checkbox" checked={this.state.checkbox1} onChange={this.selectCheckbox1} />
      <input type="checkbox" checked={this.state.checkbox2} onChange={this.selectCheckbox2} />
      <input type="checkbox" checked={this.state.checkbox3} onChange={this.selectCheckbox3} />
      ...
    </div>
  );
}

例如,我可以使用数组作为状态而不是单个字段,并创建一个通用函数,该函数使用索引参数来区分要更新的复选框:

const Checkboxes = React.createClass({
  getInitialState: function () {
    return {
      checkboxes: [false, false, false, ...]
    };
  },

  selectCheckbox: function (index) {
    let checkboxes = this.state.checkboxes.slice();
    checkboxes[index] = !checkboxes[index];
    this.setState({
      checkboxes: checkboxes
    });
  },

  render: function () {
    return (
      <div>
        <input type="checkbox" checked={this.state.checkboxes[0]} onChange={() => this.selectCheckbox(0)} />
        <input type="checkbox" checked={this.state.checkboxes[1]} onChange={() => this.selectCheckbox(1)} />
        <input type="checkbox" checked={this.state.checkboxes[2]} onChange={() => this.selectCheckbox(2)} />
        ...
      </div>
    );
  }
});

我是React和JavaScript的新手,所以我不知道这里幕后发生的权衡。第二个是第一个改进吗?哪个是首选,为什么?

3 个答案:

答案 0 :(得分:3)

第二个肯定比第一个更好。你可以安全地使用它。

除此之外,您还可以使用数组映射渲染复选框,而不是每次在渲染函数中重复它们。

render: function () {
    return (
      <div>
        {this.state.checkboxes.map((c, i) => {
             return (
              <input key={i} type="checkbox" checked={c} onChange={() => this.selectCheckbox(i)} />
           );
         })}
      </div>
    );
  }

答案 1 :(得分:1)

我会做这样的事情:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      checkboxes: {
        cheese: false,
        lettuce: false,
        tomatoe: false
      }
    };
  }

  handleChange = e => {
    const checkboxId = e.target.id;
    this.setState({
      checkboxes: {
        ...this.state.checkboxes,
        [checkboxId]: !this.state.checkboxes[checkboxId]
      }
    });
  };

  render() {
    return (
      <div>
        {Object.entries(this.state.checkboxes).map(([key, val]) => {
          return (
            <div key={key}>
              <input
                type="checkbox"
                checked={val}
                id={key}
                onChange={this.handleChange}
              />
              <label>
                {key}
              </label>
            </div>
          );
        })}
      </div>
    );
  }
}

这使事情更加明确,更容易理解,并且每次渲染时都不会创建新的匿名函数。

答案 2 :(得分:1)

我更喜欢将复选框命名为(在对象中,而不是数组中),就像在第一个示例中一样。但这可能因用例而异。正如Prakash-sharma指出的那样,将它们命名为数组,可以提供映射它们的好处。

这就是我如何减少回调函数声明的重复(不将复选框值存储在数组中):

const Checkboxes = React.createClass({
  getInitialState: function () {
    return {
      checkbox1: false,
      checkbox2: false,
      checkbox3: false
    };
  },

  selectCheckbox: function (checkboxNr) {
    // return a callback with the checkboxNr set
    return () => {
        this.setState({
         [checkboxNr]: !this.state[checkboxNr]
        });
    }
  },

  render: function () {
    const {checkboxes1, checkboxes2, checkboxes3} = this.state;
    return (
      <div>
        <input type="checkbox" checked={checkboxes1} onChange={ this.selectCheckbox("checkbox1") } />
        <input type="checkbox" checked={checkboxes2} onChange={ this.selectCheckbox("checkbox2") } />
        <input type="checkbox" checked={checkboxes3} onChange={ this.selectCheckbox("checkbox3") } />
      </div>
    );
  }
});