我有一个外部(组件),可观察对象,我想监听的变化。当对象更新时,它会发出更改事件,然后我希望在检测到任何更改时重新呈现组件。

使用顶级React。渲染这是可能的,但在组件中它不起作用(这是有意义的,因为渲染方法只返回一个对象)。

下面是一个代码示例:

export default class MyComponent extends React.Component {

  handleButtonClick() {
    this.render();
  }

  render() {
    return (
      <div>
        {Math.random()}
        <button onClick={this.handleButtonClick.bind(this)}>
          Click me
        </button>
      </div>
    )
  }
}

在内部单击按钮会调用this.render(),但这并不是真正导致呈现发生的原因(您可以在操作中看到这一点,因为由{Math.random()}创建的文本没有改变)。但是,如果我简单地调用this.setState()而不是this.render(),它就可以正常工作。

所以我想我的问题是:React组件需要有状态才能渲染吗?是否有一种方法可以在不改变状态的情况下强制组件按需更新?


当前回答

我发现最好避免使用forceUpdate()。强制重新呈现的一种方法是在临时外部变量上添加render()依赖项,并在需要时更改该变量的值。

下面是一个代码示例:

class Example extends Component{
   constructor(props){
      this.state = {temp:0};

      this.forceChange = this.forceChange.bind(this);
   }

   forceChange(){
      this.setState(prevState => ({
          temp: prevState.temp++
      })); 
   }

   render(){
      return(
         <div>{this.state.temp &&
             <div>
                  ... add code here ...
             </div>}
         </div>
      )
   }
}

当你需要强制重新渲染时,调用this.forceChange()。

其他回答

应该避免使用forceUpdate,因为它偏离了React的思维模式。React文档引用了一个何时使用forceUpdate的例子:

默认情况下,当组件的状态或道具改变时,组件将重新呈现。然而,如果这些隐式变化(例如:对象内部的深层数据变化而不改变对象本身),或者如果你的render()方法依赖于一些其他数据,你可以通过调用forceUpdate()告诉React它需要重新运行render()。

然而,我想提出这样的观点:即使对于嵌套很深的对象,forceUpdate也是不必要的。通过使用不可变数据源跟踪更改变得便宜;更改总是会产生一个新对象,因此我们只需要检查对对象的引用是否已更改。你可以使用Immutable JS库将不可变数据对象实现到你的应用程序中。

通常情况下,你应该尽量避免使用forceUpdate(),只从这个中读取。道具和这个。render()中的状态。这使得你的组件“纯粹”,你的应用程序更简单、更高效。

改变你想要重新渲染的元素的键也可以。通过state在元素上设置键道具,然后当你想更新Set state时有一个新的键。

<Element key={this.state.key} /> 

然后发生了变化,您重置了密钥

this.setState({ key: Math.random() });

我要注意的是,这将取代键改变的元素。这可能有用的一个例子是,当您有一个文件输入字段,您希望在图像上传后重置。

虽然OP问题的真正答案是forceUpdate(),但我发现这个解决方案在不同的情况下都很有用。我还想指出的是,如果你发现自己使用了forceUpdate,你可能需要检查你的代码,看看是否有另一种方法来做事情。

注意1-9-2019:

以上(改变键)将完全替换元素。如果您发现自己正在更新键来进行更改,那么您的代码中的其他地方可能存在问题。在key中使用Math.random()将在每次渲染时重新创建元素。我不建议像这样更新键,因为react使用键来确定重新渲染事物的最佳方式。

我发现最好避免使用forceUpdate()。强制重新呈现的一种方法是在临时外部变量上添加render()依赖项,并在需要时更改该变量的值。

下面是一个代码示例:

class Example extends Component{
   constructor(props){
      this.state = {temp:0};

      this.forceChange = this.forceChange.bind(this);
   }

   forceChange(){
      this.setState(prevState => ({
          temp: prevState.temp++
      })); 
   }

   render(){
      return(
         <div>{this.state.temp &&
             <div>
                  ... add code here ...
             </div>}
         </div>
      )
   }
}

当你需要强制重新渲染时,调用this.forceChange()。

有几种方法来渲染你的组件:

最简单的解决方案是使用forceUpdate()方法:

this.forceUpdate()

另一个解决方案是在状态下创建未使用的键(nonUsedKey) 然后调用setState函数更新这个nonUsedKey:

this.setState({ nonUsedKey: Date.now() } );

或者重写所有当前状态:

this.setState(this.state);

道具改变也提供了组件渲染。

当你想要两个React组件进行通信时,它们不受关系(父子关系)的约束,建议使用Flux或类似的架构。

您要做的是监听可观察组件存储的变化,该存储保存模型及其接口,并将导致呈现变化的数据保存为MyComponent中的状态。当存储推送新数据时,更改组件的状态,这会自动触发呈现。

通常你应该尽量避免使用forceUpdate()。从文档中可以看到:

通常情况下,你应该尽量避免使用forceUpdate(),只从这个中读取。道具和这个。render()中的状态。这使您的应用程序更加简单和高效

ES6 -我包括一个例子,这对我很有帮助:

在一个“简短的if语句”中,你可以像这样传递一个空函数:

isReady ? ()=>{} : onClick

这似乎是最短的方法。

()=>{}