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

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

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

使用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(),则可以正常工作。

所以我猜我的问题是:React 组件需要有状态才能重新渲染?有没有办法强制组件按需更新而不改变状态?

997

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

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

在函数组件中,没有forceUpdate的等价物,但您可以contrive a way to force updates with the useState hook

420

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

默认情况下,当您的组件的状态或道具发生变化时,您的组件将重新渲染。但是,如果这些隐式更改(例如:对象内部的数据在不更改对象本身的情况下更改),或者如果您的 render()方法依赖于其他一些数据,则可以通过调用 forceUpdate()告诉 React 它需要重新运行 render()。

但是,我想提出这样的想法,即使使用深度嵌套的对象,forceUpdate也是不必要的。通过使用不可变的数据源跟踪更改变得便宜;更改将始终导致新对象,因此我们只需要检查对对象的引用是否已更改。您可以使用库Immutable JS将不可变的数据对象实现到您的应用程序中。

通常,您应该尽量避免使用 forceUpdate(),而只从 render()中的 this.props 和 this.state 读取。这使您的组件“纯净”,并且您的应用程序更简单,更高效。forceUpdate()

更改要重新呈现的元素的键将起作用。通过 state 在元素上设置键 prop,然后当您要更新 set state 以具有新键时。

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

然后发生更改并重置密钥

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

我想指出的是,这将替换键正在更改的元素。这可能有用的一个例子是,当您有一个文件输入字段,您希望在图像上传后重置。

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

注 1-9-2019:

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

139

在 2021 年和 2022 年,这是the official way强制更新 React 功能组件。

const [, forceUpdate] = useReducer(x => x + 1, 0);
  function handleClick() {
    forceUpdate();
  }

我知道 OP 是一个类组件。但这个问题是在 2015 年提出的,现在钩子可用,许多人可能会在功能组件中搜索forceUpdate。这一点点是给他们的。

编辑 2022 年 4 月 18 日

强制更新组件通常是不好的做法。

可能导致需要使用强制更新的一些原因。

不使用状态变量,你必须-本地,redux,上下文。

您试图访问并期望更新 / 更改的状态对象中的字段在对象或数组中嵌套得太深。即使 Redux 也建议维护平面对象或数组。如果一个复杂对象中只有一个字段值发生更改,React 可能无法确定状态对象已更改,因此它不会更新组件。保持你的状态平坦和简单。

您的列表项目上的键。如另一个答案中提到的。实际上,这也可能导致其他意外行为。我已经看到列表中的项目被重复渲染 (重复),因为键不相同或键只是完全缺失。总是要求后端团队尽可能地发送唯一的 id!避免使用数组索引的键。不要试图通过使用 nanoid,uuid 或 random 在前端创建唯一的 id

如果你的 useEffect,useCallback 依赖数组没有设置正确的值。使用 ESLint 来帮助你这个!另外,这是 React 中内存泄漏的最大原因之一。在返调中清理你的状态和事件以避免内存泄漏。因为这样的内存泄漏非常难以调试。

始终关注控制台。它是您工作中最好的朋友。解决控制台中显示的警告和错误可以修复很多令人讨厌的事情-您甚至都没有意识到的错误和问题。

我记得有几件事我做错了。万一有帮助..

114

实际上,forceUpdate()是唯一正确的解决方案,因为如果在shouldComponentUpdate()中实现了其他逻辑,则setState()可能不会触发重新渲染。

forceUpdate ()

调用forceUpdate()将导致在组件上调用render(),跳过shouldComponentUpdate()more...

setState ()

setState()将始终触发重新渲染,除非在shouldComponentUpdate()中实现了条件渲染逻辑。more...

Hooks:How can I force component to re-render with hooks in React?

BTW:你是变异状态还是你的嵌套属性不传播?

How to update nested state properties in React Sandbox

本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处

(590)
使用标准对 actix_webapi进行基准测试时出现问题
上一篇
NameError:未定义名称 'line'。你的意思是:'slice'
下一篇

相关推荐

  • 厌氧塔cod去除率:去除反应时的去除作用(how to set up reaction roles)

    关于厌氧塔cod去除率的问题,在how to set up reaction roles中经常遇到,当反应被删除时,我正在尝试删除角色。我已经有了完美工作的 '添加反应' 角色。但是,每当我尝试运行这个时,它最终会打印“removed None”(none as the role),这意味着它不会删除角色。我认为这与获取角色有关。这里是代码:…

    2022-11-28 06:53:34
    0 64 75
  • 数控g84攻牙怎么编程:TI-84损坏的程序(how to reset calculator ti 84)

    关于数控g84攻牙怎么编程的问题,在how to reset calculator ti 84中经常遇到,所以几个月前我得到了一个 TI-84 计算器。截至今天早上,我有 30 个自己编写的程序存储在其中。最大的程序略超过 200 个,绝大多数在 100 个以下。RAM Free 约为 14900,而 ARC Free 一直是 1919K。…

    2022-12-14 01:34:48
    0 25 48
  • Be cl in 1:=OFFSET($A$1 MOD(ROW()-ROW($CL$1) ROWS($A$1:$A$281))

    关于Be cl in 1的问题,在excel rows function中经常遇到,经过 Google 搜索,我了解到以下函数(或更确切地说,函数混合)堆叠现有列:= OFFSET($A $1,MOD(ROW()-ROW($CL $1),ROWS($A $1:$A $281)),TRUNC((ROW()-ROW($CL $1))/ ROWS($A $1:$A $281)1,…

    2022-12-24 08:30:36
    0 84 93
  • Superset:Apache SuperSet架构

    我有点困惑 Superset 如何处理查询。根据我的轻描淡写 Superset 只存储元数据即用户,仪表板定义。它不会存储查询数据?…

    2022-12-06 04:54:46
    0 48 82
  • charset为西班牙窗口

    西班牙窗户的字符集是什么?…

    2022-11-11 15:21:01
    0 65 64
  • 您可以强制React组件在不调用setState的情况下重新渲染吗

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

    2022-12-14 02:30:04
    0 59 20
  • DynamicsCRM2013:工作流设计器布尔值和Optionset字段设置值消失

    背景:我是在 CRM 2013 SP1 RU 3 上运行的系统管理员…

    2022-11-27 03:21:05
    0 84 55
  • css预编译器: center;}

    CSS预编译器是一种用于构建CSS的工具,它可以将CSS代码转换为更易于管理和维护的格式。它们可以使CSS代码更加灵活,更易于重用,并且可以帮助开发人员更轻松地组织和管理CSS代码。…

    2023-01-05 06:29:43
    0 27 88

发表评论

登录 后才能评论

评论列表(67条)