简单的添加/删除组件模式

Simple Add / Remove Component Pattern

我对 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 次。您可以看到为什么这可能是个问题。

这看起来效率很低,有更好的方法吗?

如果您想手动管理 dom,React 可能不适合您。如果你真的愿意,你总是可以比抽象做得更好。

在 React 中,通常最好的目标是能够清楚地表达其 React 意图的代码,并让它做它的事情。

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

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


这与问题无关,但是this.props.index--是在修改道具,这很糟糕而且不可靠。如果你因为某些原因需要保留一个计数器,直接在 componentWillMount 中的 this 上设置它。如果你需要在树上传达一些东西,你接受一个回调作为道具,然后调用它。

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