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

使用顶级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()方法:

this.forceUpdate()

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

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

或者重写所有当前状态:

this.setState(this.state);

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

其他回答

在类组件中,可以调用this.forceUpdate()来强制渲染。

文档:https://facebook.github.io/react/docs/component-api.html

在函数组件中,没有等效的forceUpdate,但您可以通过useState钩子设计一种强制更新的方法。

我通过执行以下操作避免了forceUpdate

错误方法:不使用索引作为键

this.state.rows.map((item, index) =>
   <MyComponent cell={item} key={index} />
)

正确方法:使用数据id作为键,它可以是一些guid等

this.state.rows.map((item) =>
   <MyComponent item={item} key={item.id} />
)

所以通过这样的代码改进,你的组件将是唯一的,呈现自然

为了完整性,你也可以在功能组件中实现:

const [, updateState] = useState();
const forceUpdate = useCallback(() => updateState({}), []);
// ...
forceUpdate();

或者,作为一个可重复使用的钩子:

const useForceUpdate = () => {
  const [, updateState] = useState();
  return useCallback(() => updateState({}), []);
}
// const forceUpdate = useForceUpdate();

参见:https://stackoverflow.com/a/53215514/2692307

请注意,使用强制更新机制仍然是不好的做法,因为它违背了反应的心态,所以如果可能的话仍然应该避免。

实际上,forceUpdate()是唯一正确的解决方案,因为如果在shouldComponentUpdate()中实现了额外的逻辑,或者当它只是返回false时,setState()可能不会触发重新呈现。

强制更新()

调用forceUpdate()将导致在组件上调用render(),跳过shouldComponentUpdate()。更多…

设置状态()

setState()总是会触发重新呈现,除非在shouldComponentUpdate()中实现了条件呈现逻辑。更多…

forceUpdate()可以通过this.forceUpdate()从组件中调用

钩子:如何在React中使用钩子强制组件重新渲染?

顺便说一句:你是在改变状态还是你的嵌套属性不传播?

如何在React中更新嵌套的状态属性 沙盒

我们可以如下所示使用this.forceUpdate()。

       class MyComponent extends React.Component {



      handleButtonClick = ()=>{
          this.forceUpdate();
     }


 render() {

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

 ReactDOM.render(<MyComponent /> , mountNode);

元素的数学。即使你使用setState重新渲染组件,DOM中的random'部分也只会被更新。

这里所有的答案都是正确的,补充了理解..的问题,因为我们知道重新呈现一个组件不使用setState({})是通过使用forceUpdate()。

上面的代码使用setState运行,如下所示。

 class MyComponent extends React.Component {



             handleButtonClick = ()=>{
                this.setState({ });
              }


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

ReactDOM.render(<MyComponent /> , mountNode);