如何强制更新 React 组件

介绍

在本文中,我们将向您展示如何在 React.js 中强制更新组件。 更具体地说,我们将简要介绍 React 重新渲染,我们将展示如何在基于类的组件中强制更新,以及如何在功能组件中强制更新。

反应重新渲染

在大多数情况下,React 本身会自动为您处理重新渲染组件。 造成这种情况的原因可能是 props 或 state 的更新时间。 因此,当状态或属性发生变化时,组件会重新渲染。 但是,如果您的组件依赖于其他东西而不一定依赖于您的状态或属性怎么办? 在这种情况下,您可能需要强制更新组件,因为 React 可能没有检测到更改。

让我们看看如何在 React 组件上使用这种强制更新。 为了展示这一点,我们将创建一个用于演示目的的简单应用程序。

备注:我们将介绍 React 的一些概念,因此最好具备 React 的基本知识。

强制更新基于类的组件

类组件有一个用于重新渲染组件的内置方法,称为 forceUpdate(),用于强制组件重新渲染。 您可以阅读更多关于 forceUpdate() React 的方法 官方网站.

handleForceupdateMethod() {
    
    this.forceUpdate();
}

备注:不建议依赖于使用 forceUpdate() 方法。 当您发现自己需要这种方法时,您应该首先尝试分析您的代码并找出 React 没有更新组件的其他原因。 你可能会发现一个 bug 导致了这种情况,或者你可以重组你的代码,让 React 能够自行正确地重新渲染组件。

下面是一个如何强制更新基于类的组件的示例:

import React from 'react'

class App extends React.Component {
    constructor() {
        super();
        this.handleForceupdateMethod = this.handleForceupdateMethod.bind(this);
    };

    handleForceupdateMethod() {
        this.forceUpdate();
    };

    render() {
        return (
            <div>
                <h1>Hello StackAbuse</h1>
                <h3>Random Number: { Math.random() }</h3>
                <button onClick={this.handleForceupdateMethod}>
                    Force re-render
                </button>
            </div>
        );
    }
}

export default App

这种方法中发生的事情比看起来要多得多。 例如,调用 forceUpdate() 也触发子组件的生命周期方法。 正如我们在 React 中所知道的,只有在标记实际发生变化时它才会更新 DOM。

你可以访问 现场代码在这里.

强制更新功能组件

函数式组件没有像基于类的组件那样重新渲染组件的内置方法。 这意味着我们没有 forceUpdate() 我们可以使用的方法。 但是,请回想一下,在 React 中,组件通常会由于状态或 prop 更改而重新渲染。 使用它,我们可以实现强制更新的方法。

从 v16.8+ 开始,React 有一个称为 Hooks 的概念,它可以在功能组件中用于更新状态、执行副作用等。我们将利用这些 hooks 来让组件重新渲染。

以下是一些关于如何在功能组件中强制更新的示例:

使用 useReducer

const [ignored, forceUpdate] = useReducer(x => x + 1, 0);

function handleClick() {
    forceUpdate();
}

当你有复杂的状态逻辑和动作时,通常会使用 React 中的 reducer。 在这里,我们通过更新一个虚拟状态变量来简单地使用它来触发更新, x. 状态必须实际更改才能触发更新,这就是每次调用都会增加状态的原因。

使用 useState

import React, { useState } from "react";


function useForceUpdate() {
    let [value, setState] = useState(true);
    return () => setState(!value);
}

export default function App() {
    
    const handleForceupdateMethod = useForceUpdate();

    return (
        <div className="App">
            <h1>Hello StackAbuse </h1>
            <h3>Random Number: { Math.random() }</h3>

            {/*
                Clicking on the button will force to re-render like force update does
            */}
            <button onClick={handleForceupdateMethod}>Force re-render</button>
        </div>
    );
}

查看我们的 Git 学习实践指南,其中包含最佳实践、行业认可的标准以及随附的备忘单。 停止谷歌搜索 Git 命令,实际上 学习 它!

这种强制更新背后的想法非常类似于 useReducer 因为我们不断更新状态来强制改变。 不像我们在上一个方法中那样增加一个计数器,这里我们简单地切换一个布尔值,以便在每次调用时都将其取反。

使用 useStateuseCallback 挂钩

import React, { useState , useCallback} from "react";

export default function App() {
    const [, updateState] = useState();
    const handleForceupdateMethod = useCallback(() => updateState({}), []);

    
    console.log("Rendering...");

    return (
        <div className="App">
            <h1>Hello StackAbuse</h1>
            <h3>Random Number: { Math.random() }</h3>

            {/*
                Clicking on the button will force to re-render like force update does
            */}
            <button onClick={handleForceupdateMethod}>Force re-render</button>
        </div>
    );
}

同样,此策略通过更改状态来起作用。 在这种情况下,虽然我们没有在技术上改变 折扣值 国家的,我们 ,那恭喜你, 向它发送一个新对象,React 认为它是新对象,因为它不对状态进行“深度”相等检查。

如您所见,这里有多种方法可以实现相同的目标。 请记住,这些都是技术上的反模式,应尽可能避免。 但是,如果您无法解决根本问题并且需要强制更新组件,那么我们在此处展示的任何方法都应该可以工作。

结论

在本文中,我们看到了如何强制更新 React 组件。 我们还看到了如何在函数式组件和基于类的组件中实现这一点。 虽然不一定是好的做法,但如果我们需要在特殊情况下使用它,了解它的工作原理是有用的。

时间戳记:

更多来自 堆栈滥用