您可以在不调用setState的情况下强制React组件重新呈现吗?

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

对于顶层,React.render这是可能的,但是在组件内不起作用(这是有道理的,因为该render方法仅返回一个对象)。

这是一个代码示例:

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(),它就可以正常工作。

So I guess my question is: do React components need to have state in order to rerender? Is there a way to force the component to update on demand without changing the state?

猪猪十三2020/03/09 22:36:29

您可以使用forceUpdate()进行更多详细信息检查(forceUpdate())。

Tony老丝2020/03/09 22:36:29

forceUpdate(),但是每次我听到有人谈论它时,都应该跟进它,但绝对不要使用它。

路易Itachi小小2020/03/09 22:36:29

ES6-我提供了一个示例,这对我有帮助:

在“ short if语句”中,您可以传递空函数,如下所示:

isReady ? ()=>{} : onClick

这似乎是最短的方法。

()=>{}
神乐神无2020/03/09 22:36:29

为了完成您描述的内容,请尝试this.forceUpdate()。

TonyMandy2020/03/09 22:36:29

另一种方法是调用setState保留状态:

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

十三JimHarry2020/03/09 22:36:29

forceUpdate(); 该方法可以使用,但建议使用 setState();

猿神奇梅2020/03/09 22:36:29

我发现最好避免使用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()。

乐泡芙2020/03/09 22:36:29

我们可以如下使用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中的元素“ Math.random”部分也只会更新。

这里所有的答案都是对问题理解的正确补充。.我们知道通过使用forceUpdate()无需使用setState({})就可以重新渲染组件。

上面的代码与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);
泡芙Pro2020/03/09 22:36:29

只是另一个回复,以备份已接受的答案:-)

React不鼓励使用,forceUpdate()因为它们通常在函数式编程中使用非常“这是唯一的方法”。在许多情况下这很好,但是许多React开发人员都带有面向对象的背景,通过这种方法,完全可以监听可观察对象。

如果这样做了,您可能知道您必须在可观察到的“火灾”发生时重新渲染,因此,您应该使用forceUpdate()它,而实际上这shouldComponentUpdate()是这里不涉及的优点。

MobX之类的工具需要面向对象的方法,实际上是在表面下进行此操作(实际上是MobX render()直接调用

小宇宙西里2020/03/09 22:36:29

有几种方法可以重新渲染组件:

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

this.forceUpdate()

另一种解决方案是在state(nonUsedKey)中创建未使用的密钥,并通过更新此nonUsedKey来调用setState函数:

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

或重写所有当前状态:

this.setState(this.state);

更改道具也可以重新渲染组件。

Tony小卤蛋2020/03/09 22:36:29

为了完整起见,您还可以在功能组件中实现此目的:

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

请注意,使用强制更新机制仍然是不正确的做法,因为它会违反反应心态,因此,如果可能的话,仍应避免使用它。

Jim小哥GO2020/03/09 22:36:29

您可以通过以下两种方法进行操作:

1.使用forceUpdate()方法:

使用该forceUpdate()方法时可能会发生一些故障一个示例是它忽略该shouldComponentUpdate()方法,并且无论是否shouldComponentUpdate()返回false 都将重新渲染视图因此,应尽可能避免使用forceUpdate()。

2.将this.state传递给setState()方法

以下代码行克服了上一个示例的问题:

this.setState(this.state);

实际上,所有要做的就是用触发重新渲染的当前状态覆盖当前状态。这仍然不一定是最好的处理方法,但是它确实克服了使用forceUpdate()方法可能遇到的一些故障。

Tom西里2020/03/09 22:36:29

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

其他答案试图说明您如何做到,但重点是您不应该这样做即使是更改密钥的骇人听闻的解决方案也没有抓住重点。React的功能是放弃手动管理何时应该渲染某些东西的控制权,而只是考虑如何在输入上映射东西。然后提供输入流。

如果您需要手动强制重新渲染,则几乎可以肯定您没有做正确的事情。

Mandy猴子2020/03/09 22:36:29

在您的组件中,您可以调用this.forceUpdate()强制重新渲染。

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

Eva梅2020/03/09 22:36:29

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} />
)

因此,通过进行此类代码改进,您的组件将是唯一的并自然呈现

猴子阳光2020/03/09 22:36:29

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

您要做的是监听可观察的组件存储(包含模型及其接口)的更改,并保存导致渲染更改的数据,如state中所示MyComponent当商店推送新数据时,您将更改组件的状态,这将自动触发渲染。

通常,您应尽量避免使用forceUpdate()从文档中:

通常,您应该避免使用forceUpdate(),而只能从render()中的this.props和this.state中读取。这使您的应用程序更简单,更高效

猪猪GO2020/03/09 22:36:29

实际上,这forceUpdate()是唯一正确的解决方案,因为如果在其中或仅返回时实施了附加逻辑,则setState()可能不会触发重新渲染shouldComponentUpdate()false

强制性升级()

调用forceUpdate()将导致render()在组件上被跳过shouldComponentUpdate()更多...

setState()

setState()除非在中实现了条件渲染逻辑,否则它将始终触发重新渲染shouldComponentUpdate()更多...


forceUpdate() 可以从组件内部调用 this.forceUpdate()


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