React - 如何强制功能组件呈现?

IT技术 javascript reactjs react-functional-component
2021-01-13 21:45:28

我有一个函数组件,我想强制它重新渲染。

我该怎么做?
由于没有实例this,我无法调用this.forceUpdate()

6个回答

🎉 你现在可以,使用React 钩子

使用 React 钩子,您现在可以调用useState()您的函数组件。

useState() 将返回一个包含 2 个东西的数组:

  1. 一个值,表示当前状态。
  2. 它的二传手。使用它来更新值。

通过其 setter 更新值将强制您的函数组件重新渲染
就像这样forceUpdate做:

import React, { useState } from 'react';

//create your forceUpdate hook
function useForceUpdate(){
    const [value, setValue] = useState(0); // integer state
    return () => setValue(value => value + 1); // update the state to force render
}

function MyComponent() {
    // call your hook here
    const forceUpdate = useForceUpdate();
    
    return (
        <div>
            {/*Clicking on the button will force to re-render like force update does */}
            <button onClick={forceUpdate}>
                Click to re-render
            </button>
        </div>
    );
}

您可以在此处找到演示

上面的组件使用了一个自定义的钩子函数 ( useForceUpdate),它使用了react状态钩子useState它增加组件的状态值,从而告诉 React 重新渲染组件。

编辑

在此答案的旧版本中,该代码段使用了一个布尔值,并在forceUpdate(). 现在我已经编辑了我的答案,代码片段使用数字而不是布尔值。

为什么 ?(你会问我)

因为有一次我碰巧forceUpdate()从 2 个不同的事件中随后两次调用了 my ,因此它将布尔值重置为其原始状态,并且组件从未呈现。

这是因为在useState's setter ( setValuehere ) 中,React将前一个状态与新状态进行比较,并且仅在状态不同时才渲染。

嗨@DanteTheSmith。正如您所说,“顶级”意味着不能从条件或循环内部调用钩子。但我可以告诉你,你可以从另一个函数内部调用它们。这意味着创建一个自定义钩子。Dan Abramov 在 React conf 中介绍 React hooks 时,清楚地表明这是在功能组件之间共享逻辑的最干净和最好的方式:youtu.be/dpw9EHDh2bM?t=2753
2021-03-20 21:45:28
无需切换任何状态“强制渲染”。你造成了一个错误的印象,即 React “比较” prev 和 next 状态值来决定是否需要重新渲染。虽然它绝对没有。
2021-03-22 21:45:28
该页面上没有任何关于使用 Hooks 调用的信息forceUpdate
2021-03-30 21:45:28
@meandre 是的,它绝对可以比较。我们谈论的是useState钩子,而不是setState确实无法进行比较的类(除非您实现了 shouldUpdate 方法)。请参阅我发布的相同演示,但使用用于 的静态值setState,它不会再次呈现:codesandbox.io/s/determined-rubin-8598l
2021-04-01 21:45:28
现在,你是对的,它更好,因为即使还没有发布强硬的钩子,你仍然可以在测试版中使用它。但是一旦它们被发布,类组件没有理由会更好。使用钩子使代码比类组件更干净,如下面的 reactconf 视频所示。无论如何,问题是这是否可能。由于挂钩,答案现在从“否”变为“是”。youtube.com/watch?v=wXLf18DsV-I
2021-04-06 21:45:28

更新 react v16.8(2019 年 2 月 16 日发布)

自从react 16.8 发布了钩子,函数组件现在可以保持持久化state有了这种能力,你现在可以模仿一个forceUpdate

请注意,应该重新考虑这种方法,并且在大多数情况下,当您需要强制更新时,您可能做错了什么。


react前 16.8.0

不,你不能,无状态函数组件只是正常的functions返回jsx,你没有任何访问 React 生命周期方法的权限,因为你没有从React.Component.

将函数组件视为render类组件方法部分。

“当你需要强制更新时,你可能做错了什么”的道具 - 我知道是这种情况,但这只是促使我再仔细看看我的 useEffect 钩子。
2021-03-21 21:45:28
你可以。改变它的道具
2021-03-26 21:45:28
这不是强制重新渲染,这只是一个正常的渲染。当您想强制渲染时,通常是在渲染方法未设计为运行时想要运行渲染方法的情况,例如当没有新的propsstate更改时。不能强制渲染功能,因为render无状态组件没有功能。无状态组件extends React.Component不仅仅是返回jsx.
2021-04-03 21:45:28

如果您确实需要这样做,官方常见问题解答(https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate)现在推荐这种方式

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

  function handleClick() {
    forceUpdate();
  }
并且您可以将代码缩短 7 个字节,并且不要创建未使用的变量: const [, forceUpdate] = useReducer(x => x + 1, 0);
2021-03-28 21:45:28

我使用了一个名为use-force-update 的第三方库 来强制渲染我的 React 功能组件。像魅力一样工作。只需在您的项目中使用导入包并像这样使用。

import useForceUpdate from 'use-force-update';

const MyButton = () => {

  const forceUpdate = useForceUpdate();

  const handleClick = () => {
    alert('I will re-render now.');
    forceUpdate();
  };

  return <button onClick={handleClick} />;
};
为了节省您的点击次数 -useForceUpdate使用useCallback其他答案中提到的。这个库只是一个实用程序库,可以为您节省几次按键操作。
2021-03-25 21:45:28

免责声明:不是问题的答案。

在此留下重要说明:

如果您尝试强制更新无状态组件,则您的设计可能有问题。

考虑以下情况:

  1. 将 setter (setState) 传递给可以更改状态并导致父组件重新渲染的子组件。
  2. 考虑提升状态
  3. 考虑将该状态放在您的 Redux 存储中,它可以自动强制重新渲染连接的组件。
在现实世界中,它是有用途的。没有什么是完美的,如果您想将软件推出市场,您最好知道当其他人搞砸时如何让事情发生。
2021-03-25 21:45:28
我有一个案例,我需要禁用组件更新并在我想要的时候强制它(是一个移动的标尺,它会在每次移动时更新它的值,并且更新会导致闪烁的行为)。所以我决定在这个组件上使用类,我建议所有需要对渲染行为进行深度控制的组件都应该在类中完成,因为当前钩子不能很好地控制这种行为。(当前 React 版本是 16.12)
2021-03-30 21:45:28
我也这么想,但是,我想要一个快速修复,所以我使用了强制更新。
2021-04-08 21:45:28