简单添加/删除组件模式

时间:2015-02-06 00:58:37

标签: javascript design-patterns reactjs

我对React中的这种模式感到很困惑。我在其他地方看过它,但它似乎不正确。

鉴于以下代码:

/** @jsx React.DOM */

var React = window.React = require('react'),
    Item = require("./ui/Item");

var ItemApp = React.createClass({
  getInitialState: function() {
    return {
      items: [ "Example Item" ] // we want one thing to render initially
    };                          // so prepopulate with one thing
  },
  getDefaultProps: function () {
    return {
      index: 1
    }
  },
  onAddItem: function (e) {
    var debts = this.state.debts.push( "New Item " + this.props.index);
    this.setState({ items: this.state.items });
    this.props.index++;
  },
  onRemoveItem: function (i) {
    // splice here
    this.state.items.splice(i, 1);
    this.setState({ items: this.state.items });
    this.props.index--;
  },
  render: function () {
    var items = this.state.items;
    var closeFn = this.onRemoveItem;
    return (
      <div className="col-lg-12">
        <div className="cold-md-3"></div>
        <div className="col-md-3 col-md-offset-9">
          <button type="button" className="btn btn-default" onClick={this.onAddItem}><span className="glyphicon glyphicon-plus"></span> Add New Debt</button>
        </div>
        {items.map(function (item, i) {
          return <Item name={item} closeFn={closeFn.bind(null, i)} key={i} />;
        })}
      </div>
    );
  }
});

上面的例子就像预期的那样(它是一个列表,你可以随意添加和删除东西)但是每当我添加一些东西时,整个事情都会重新呈现。

因此,在仅添加一个组件后,整个事件已呈现3次。点击两次后,它将渲染5次。你可以看出为什么这可能是一个问题。

这似乎真的效率低下是否有更好的方法来做到这一点?

1 个答案:

答案 0 :(得分:2)

如果你想手动管理dom,反应可能不适合你。如果你真的想要,你总是可以比抽象更好。

作为反应,通常最好的目标是能够清楚地表达其反应意图的代码,并让它做到这一点。

您的代码已接近,唯一的问题是您的key属性不能唯一地反映数组中的项目。当你有一个堆栈时,基于索引的键是100%罚款。我给了一个more detailed answer类似的问题。

要在此处实际解决此问题,因为任何项目都可以随时删除,您需要在项目本身中编码唯一标识符。您应该存储一个对象数组["a", "b", "c"],而不是存储字符串数组[{id: '1', text: "a"}, {id: '2', text: "b"}, {id: '3', text: "c"}]。然后,您可以使用ID作为密钥,它会更有效。


这与问题无关,但是this.props.index--正在修改道具,这是不好的和不可靠的。如果由于某种原因需要保留计数器,请直接在componentWillMount中的this上设置。如果您需要在树上进行通信,则接受回调作为道具,然后调用它。

除了请求删除之外,<Item name={item} closeFn={closeFn.bind(null, i)} key={i} />并没有描述从项目中取回数据的任何方法。