在React.js中触发子重新渲染

Dja*_*jam 51 javascript reactjs

Parent(MyList在我的示例中)组件通过Child(MyComponent)组件呈现数组.Parent决定更改数组中的属性,React触发子重新呈现的方式是什么?

this.setState({});在调整数据后,我想出的就是在Parent中.这是一种触发更新的黑客还是反应方式?

JS小提琴:https: //jsfiddle.net/69z2wepo/7601/

var items = [
  {id: 1, highlighted: false, text: "item1"},
  {id: 2, highlighted: true, text: "item2"},
  {id: 3, highlighted: false, text: "item3"},
];

var MyComponent = React.createClass({
  render: function() {
    return <div className={this.props.highlighted ? 'light-it-up' : ''}>{this.props.text}</div>;
  }
});

var MyList = React.createClass({
  toggleHighlight: function() {
    this.props.items.forEach(function(v){
      v.highlighted = !v.highlighted;
    });

    // Children must re-render
    // IS THIS CORRECT?
    this.setState({});
  },

  render: function() {
    return <div>
      <button onClick={this.toggleHighlight}>Toggle highlight</button>
      {this.props.items.map(function(item) {
          return <MyComponent key={item.id} text={item.text} highlighted={item.highlighted}/>;
      })}
    </div>;
  }
});

React.render(<MyList items={items}/>, document.getElementById('container'));
Run Code Online (Sandbox Code Playgroud)

Jor*_*ing 43

这里的问题是你存储状态this.props而不是this.state.由于这个组件是变异的items,因此items是状态并且应该存储在其中this.state.(这是一篇关于道具与状态好文章.)这解决了你的渲染问题,因为当你更新时items你会调用setState,这将自动触发重新渲染.

这是使用state而不是props的组件的样子:

var MyList = React.createClass({
    getInitialState: function() {
        return { items: this.props.initialItems };
    },

    toggleHighlight: function() {
        var newItems = this.state.items.map(function (item) {
            item.highlighted = !item.highlighted;
            return item;
        });

        this.setState({ items: newItems });
    },

    render: function() {
        return (
            <div>
                <button onClick={this.toggleHighlight}>Toggle highlight</button>
                { this.state.items.map(function(item) {
                    return <MyComponent key={item.id} text={item.text} 
                             highlighted={item.highlighted}/>;
                }) }
            </div>
        );    
    }
});

React.render( <MyList initialItems={initialItems}/>,
              document.getElementById('container') );
Run Code Online (Sandbox Code Playgroud)

请注意,我将items道具重命名为initialItems,因为它明确表示MyList会改变它.这是文档推荐的.

你可以在这里看到更新的小提琴:https://jsfiddle.net/kxrf5329/

  • 我已经把头发拉了几天,因为我不知道这样做的最佳方法是什么.我知道状态< - props是反模式的,我不知道文档说明在这样的情况下可以做到这一点.谢谢你指出来! (2认同)

Asl*_*ekh 30

重新渲染子项的一个简单选择是每次需要重新渲染时更新唯一的键属性。

<ChildComponent key={this.state.updatedKey}/>
Run Code Online (Sandbox Code Playgroud)


小智 11

我找到了一个很好的解决方案,使用key属性重新渲染React Hook。如果我们更改了子组件或 React 组件的某些部分的关键属性,它将完全重新渲染。当您需要重新渲染 React 组件的某些部分或重新渲染子组件时,它将使用它。这是一个例子。我将重新渲染完整的组件。

import React, { useState, useEffect } from "react";
import { PrEditInput } from "./shared";

const BucketInput = ({ bucketPrice = [], handleBucketsUpdate, mood }) => {
  const data = Array.isArray(bucketPrice) ? bucketPrice : [];
  const [state, setState] = useState(Date.now());
  useEffect(() => {
    setState(Date.now());
  }, [mood, bucketPrice]);
  return (
    <span key={state}>
      {data.map((item) => (
        <PrEditInput
          key={item.id}
          label={item?.bucket?.name}
          name={item.bucketId}
          defaultValue={item.price}
          onChange={handleBucketsUpdate}
          mood={mood}
        />
      ))}
    </span>
  );
};

export default BucketInput;
Run Code Online (Sandbox Code Playgroud)

  • 为组件的关键属性设置新值将重新渲染该组件 (2认同)
  • 关键是关键! (2认同)
  • 太棒了!,这拯救了我的一天,只是想知道这里到底发生了什么魔法 (2认同)
  • 这可能是个坏主意。更改密钥将导致反应不仅重新渲染组件,而且完全重新创建它,包括完全卸载/重新安装,这对于某些复杂的组件树可能非常昂贵。 (2认同)

Lek*_*ens 7

您可以在子组件上设置数字键,并在执行操作后触发键更改。例如

state = {
        childKey: 7,
};



<ChildComponent key={this.state.childKey}/>


actionToTriggerReload = () => {
const newKey = this.state.childKey * 89; // this will make sure the key are never the same
this.setState({childKey: newKey})
   }
Run Code Online (Sandbox Code Playgroud)

这肯定会重新渲染 ChildComponent


Jer*_*y D 6

您应该通过调用setState()并提供要传播的新道具来触发重新渲染.如果你真的想强制更新,你也可以打电话forceUpdate().

如果查看此页面上的示例,您可以看到这setState是用于更新和触发重新呈现的方法.该文件还指出(ahaha!)明确.

在你的情况下我会打电话forceUpdate.

编辑:正如乔丹在评论中提到的那样,将物品存放为您所在州的一部分会更好.这样你就不必调用,forceUpdate但你真的会更新组件的状态,因此setState更新值的常规更好.