我可以在无状态组件中调用forceUpdate吗?

Gor*_*ath 30 javascript reactjs

我有一个无状态组件,我想重新渲染它.我怎么能这样做?我试过用this,但没用.

我可以改用forUpdate或其他东西吗?

Yai*_*pro 54

你现在可以使用React钩子

使用反应挂钩,您现在可以调用useState()组件功能.这将返回一个由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); // update the state to force render
}

function MyComponent() {
    // use your hook her
    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>
    );
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里找到一个演示.

上面的组件使用自定义钩子函数(useForceUpdate),它使用布尔状态钩子(useState).它切换布尔状态,从而告诉React重新运行render函数.

  • 一个空对象也会做同样的事情 (5认同)
  • @meandre 是的,它绝对可以比较。我们正在讨论 `useState` 钩子,而不是 `setState` 类,它确实不会进行比较(除非你实现 shouldUpdate 方法)。请参阅我发布的相同演示,但使用用于“setState”的静态值,它不会再次呈现:https://codesandbox.io/s/dependent-rubin-8598l (4认同)
  • 该页面上没有任何关于使用Hooks调用`forceUpdate`的信息。 (2认同)
  • 嗨@DanteTheSmith。正如您所说,“顶级”意味着不能从条件或循环内部调用钩子。但我可以告诉你,你可以从另一个函数内部调用它们。这意味着创建一个自定义钩子。Dan Abramov 在 React conf 中介绍 React hooks 时,清楚地表明这是在功能组件之间共享逻辑的最干净和最好的方式:https://youtu.be/dpw9EHDh2bM?t=2753 (2认同)

Gra*_*tei 34

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

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

  function handleClick() {
    forceUpdate();
  }
Run Code Online (Sandbox Code Playgroud)

  • 你可以让你的代码短 7 个字节并且不创建未使用的变量: `const [, forceUpdate] = useReducer(x =&gt; x + 1, 0);` (22认同)
  • 更短的 `const forceUpdate = useReducer(x =&gt; x + 1, 0)[1]` (14认同)

Sag*_*b.g 24

不,你不能,State-Less组件只是正常state返回forceUpdate,你没有任何访问React生命周期方法,因为你没有从扩展functions.

  • 这不是__forcing__重新渲染,这只是一个普通的渲染.当你想要__force__渲染时,通常情况下你想要在不设计运行时运行render方法,例如当没有新的`props`或`state`变化时.你__can't__强制渲染函数,因为无状态组件上没有`render`功能.无状态组件不"扩展"`React.Component`它们只是返回`jsx`的普通函数. (3认同)
  • “当你需要强制更新时,你可能做错了什么”的道具 - 我知道情况确实如此,但这只是促使我再仔细看看我的 useEffect 钩子。 (3认同)

Abr*_*ham 18

最简单的方法

如果您想强制重新渲染,请添加一个可以更改的虚拟状态以启动重新渲染。

const [rerender, setRerender] = useState(false);

...
setRerender(!rerender);     //whenever you want to re-render
Run Code Online (Sandbox Code Playgroud)

这将确保重新渲染,并且您可以setRerender(!rerender)随时随地调用:)

  • 请参阅另一个答案评论线程,了解这不起作用的情况(称为两次场景) (4认同)

Cha*_*nka 9

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

import useForceUpdate from 'use-force-update';

const MyButton = () => {

  const forceUpdate = useForceUpdate();

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

  return <button onClick={handleClick} />;
};
Run Code Online (Sandbox Code Playgroud)

  • 为了节省您的点击次数 - `useForceUpdate` 使用 `useCallback`,如其他答案中提到的。该库只是一个实用程序库,可以帮助您节省很少的击键次数。 (6认同)

Ank*_*rob 6

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

在此留下重要说明:

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

考虑以下情况:

  1. 将 setter (setState) 传递给可以更改状态并导致父组件重新渲染的子组件。
  2. 考虑提升状态
  3. 考虑将该状态放在您的 Redux 存储中,它可以自动强制重新渲染连接的组件。


Ale*_*lov 5

最佳方法 - 在每次渲染时不会重新创建多余的变量:

const forceUpdateReducer = (i) => i + 1

export const useForceUpdate = () => {
  const [, forceUpdate] = useReducer(forceUpdateReducer, 0)
  return forceUpdate
}
Run Code Online (Sandbox Code Playgroud)

用法:

const forceUpdate = useForceUpdate()

forceUpdate()
Run Code Online (Sandbox Code Playgroud)