简体   繁体   English

React 16强制组件在返回数组时重新渲染

[英]React 16 forces component re-render while returning array

Assume I have the next piece of code inside the React component 假设我在React组件中有下一段代码

removeItem = (item) => {
    this.items.remove(item) // this.items -> mobx array
}

renderItem = (item, index) => {
    var _item = undefined
    switch (item.type) {
        case "header":
            _item = <Header key={item.id} onRemove={() => this.removeItem(item)} />
        // a few more cases
        // note that item.id is unique and static
    }

    // return _item -> works fine
    return [
        _item,
        this.state.suggested
            ? <Placeholder key={-item.id} />
            : null
    ]
}

render() {
    return (
        <div>
            {this.items.map((item, i) => renderItem(item))}
        </div>
    )
}

Also assume that inside each of item I have a button that triggers onRemove handler with click. 还要假设在每个项目中我都有一个按钮,通过单击触发onRemove处理程序。 And each component has textarea where user can enter his text. 每个组件都有文本区域,用户可以在其中输入文本。

Obviously, when user enters text inside item's textarea, it should be saved until item will be removed. 显然,当用户在项目的文本区域内输入文本时,应保存该文本,直到将其删除。

The problem is when I remove some item, each item that goes after the removed one is being remounted (edited for Vlad Zhukov). 问题是当我删除某些项目时,要删除的每个项目都将被重新安装 (为Vlad Zhukov编辑)。 It happens only when I return an array from renderItem(...) (I mean, when I return only item, this problem doesn't happen). 仅当我从renderItem(...)返回数组时才会发生(我的意思是,当我仅返回item时,不会发生此问题)。

My question: is this a bug, or it's a feature? 我的问题:这是错误还是功能? And how can I avoid it (desirable without wrapping item and Placeholder with another React child)? 以及如何避免这种情况(最好不将项目和占位符与另一个React子项包装在一起)?


UPDATED 更新

I tried rewrite renderItem(...) the next way: 我尝试用以下方式重写renderItem(...)

renderItem = (item, index) => {
    var Item = undefined
    switch (item.type) {
        case "header":
            Item = Header
        // a few more cases
        // note that item.id is unique and static
    }

    // return _item -> works fine
    return [
        <Item key={item.id} onRemove={() => this.removeItem(item)} />,
        this.state.suggested
            ? <Placeholder key={-item.id} />
            : null
    ]
}

And it still causes the problem. 而且它仍然引起问题。

Rerendering is absolutely fine in React and can be considered the main feature. 在React中,渲染绝对好,可以认为是主要功能。 What happens in your case is components remount when you make changes to an array of elements when these elements have no key props. 在您的情况下,发生的情况是,当您对元素数组进行更改时,如果这些元素没有key道具,则会重新安装组件。

Have a look at this simple example . 看一下这个简单的例子 As you can see rerendering components has no difference but removing the first element will clear values of inputs below. 如您所见,重新渲染组件没有区别,但是删除第一个元素将清除下面的输入值。

You've got 2 options: 您有2个选择:

  1. Use a component instead of an array and set key to it (see an example). 使用组件而不是数组,并为其设置key (请参见示例)。 There is really no reason not to. 确实没有理由不这样做。
  2. Remove all key s. 拔下所有key The reason why it works is because React internally already uses keys for elements. 之所以起作用,是因为React在内部已经使用了元素的键。 However I wouldn't suggest this as it doesn't look reliable enough to me, I'd prefer to control it explicitly. 但是我不建议这样做,因为它对我而言似乎不够可靠,我希望对其进行显式控制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM