React-関数コンポーネントを強制的にレンダリングする方法は?


84

関数コンポーネントがあり、強制的に再レン​​ダリングしたいと思います。

どうすればよいですか?
インスタンスthisがないので、呼び出すことはできませんthis.forceUpdate()


いいえ、ステートレスコンポーネントには状態がありません。代わりにクラスを使用してください
TryingToImprove 2017

2
「機能コンポーネント」ではなくステートレスコンポーネント」を本当に意味するのでしょうか。
クリス

2
ステートレスコンポーネントを更新するには、渡された小道具を変更する必要があります。
fungusanthrax 2017

小道具の横でフックuseStateを使用でき、コンポーネントは変更されると再レンダリングされます
Hamid Shoja

回答:


134

🎉Reactフックを使用してできるようになりました

反応フックを使用useState()して、関数コンポーネントを呼び出すことができるようになりました。

useState() 次の2つの配列を返します。
ます。1。現在の状態を表す値。
2.そのセッター。値を更新するために使用します。

そのセッターで値を更新すると、再描画にあなたの機能コンポーネントを強制的に
同じように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() {
    // 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は、ブール状態フック(useState)を使用するカスタムフック関数()を使用します。ブール状態を切り替えて、レンダリング関数を再実行するようにReactに指示します。

編集

この回答の古いバージョンでは、スニペットはブール値を使用し、でそれを切り替えましたforceUpdate()。回答を編集したので、スニペットはブール値ではなく数値を使用します。

どうして ?(あなたは私に尋ねるでしょう)

あるときforceUpdate()、2つの異なるイベントから2回呼び出されたため、ブール値が元の状態にリセットされ、コンポーネントがレンダリングされなかったためです。

であるためuseStateのセッター(setValueここでは)、React新しいものと以前の状態を比較し、そして状態が異なる場合にのみレンダリングします。


3
そのページには、フックを使用してを呼び出すことに関する情報はありませんforceUpdate
jdelman 2018

1
今のところ、タフなフックがまだリリースされていなくても、ベータ版で使用できるので、あなたは正しいです。しかし、それらがリリースされると、クラスコンポーネントが改善される理由はありません。以下のreactconfのビデオが示すように、フックを使用すると、コードがクラスコンポーネントよりもクリーンになります。とにかく、問題はこれが可能かどうかです。フックが原因で、答えが「いいえ」から「はい」に変わります。youtube.com/watch?v=wXLf18DsV-I
Yairopro 2018

1
こんにちは@DanteTheSmith。「トップレベル」とは、あなたが言ったように、フックが条件またはループの内部から呼び出されてはならないことを意味します。しかし、別の関数の内部からそれらを呼び出すことができると言うことができます。そして、それはカスタムフックを作成することを意味します。ダン・アブラモフ監督は、彼のプレゼントが反応confには、明らかにこれは、機能コンポーネント間の共有ロジックにクリーンかつ最良の方法であることを実証してフックを反応する:youtu.be/dpw9EHDh2bM?t=2753
Yairopro

1
「レンダリングを強制する」ために状態を切り替える必要はありません。Reactが前の状態と次の状態の値を「比較」して、再レンダリングが必要かどうかを判断するという誤った印象を作成します。それは間違いなくありませんが。
蛇行

1
@meandreはい、間違いなく比較します。私たちはuseStateフックについて話しているのでsetStateあって、実際には比較を行わないクラスではありません(shouldUpdateメソッドを実装しない限り)。私が投稿したのと同じデモを参照してください。ただし、に静的な値を使用するとsetState、再度レンダリングされません。codesandbox.io
s

47

react v16.8を更新します(2019年2月16日リリース)

フックリリースされたreact16.8以降、関数コンポーネントは永続的に保持できるようになりましたstate。その能力であなたは今:を模倣することができますforceUpdate

このアプローチは再検討する必要があり、ほとんどの場合、更新を強制する必要がある場合は、おそらく何か間違ったことをしていることに注意してください。


反応する前に16.8.0

いいえ、できません。State-Less関数コンポーネントは正常でありfunctions、を返します。jsxから拡張していないため、ReactライフサイクルメソッドにアクセスできませんReact.Component

function-componentrenderは、クラスコンポーネントのメソッド部分と考えてください。


多くの場合、できます。それに来る小道具変更
マリアンジークŠedaj

5
これは再レンダリングを強制するものではなく、通常のレンダリングです。レンダリングを強制したい場合、それは通常、実行するように設計されていないときにrenderメソッドを実行したい場合です。たとえば、新しいものpropsstate変更がない場合などです。ステートレスコンポーネントには関数がないため、レンダリング関数を強制することはできませんrender。ステートレスコンポーネントはextends React.Component、を返す単なる関数ではありませんjsx
Sagiv bg 2017

「更新を強制する必要があるときは、おそらく何か間違ったことをしている」という小道具-そうだとわかっていましたが、useEffectフックをもう一度よく見るように促されました。
メソジシャン

12

公式FAQ(https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate)では、本当に必要な場合にこの方法を推奨しています。

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

  function handleClick() {
    forceUpdate();
  }

まあ、私はそれを知りませんでした
Charith Jayasanka

9
そして、あなたはあなたのコード7が短くバイト、未使用の変数を作成しないことができます:const [, forceUpdate] = useReducer(x => x + 1, 0);
コンスタンチンSmolyanin

7

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

2
クリックを節約するには-他の回答に記載されuseForceUpdateuseCallbackいるように使用します。このライブラリは、いくつかのキーストロークを節約するための単なるユーティリティライブラリです。
asyncwait

ああ、ありがとう。私はそれを知りませんでした。:)
Charith Jayasanka

6

免責事項:問題への回答ではありません。

ここに重要な注意を残します:

ステートレスコンポーネントを強制的に更新しようとしている場合は、デザインに問題がある可能性があります。

次の場合を考えてみましょう。

  1. セッター(setState)を子コンポーネントに渡します。これにより、状態が変更され、親コンポーネントが再レンダリングされます。
  2. 状態を持ち上げることを検討してください
  3. その状態をReduxストアに配置することを検討してください。これにより、接続されたコンポーネントで自動的に再レン​​ダリングが強制される可能性があります。

1
コンポーネントの更新を無効にして、必要なときに強制する必要がある場合があります(移動する定規であり、移動するたびに値が更新され、更新によってちらつきが発生します)。そのため、このコンポーネントでクラスを使用することにしました。現在、フックではこの動作を細かく制御できないため、レンダリング動作を詳細に制御する必要があるすべてのコンポーネントをクラスで実行することをお勧めします。(現在のバージョンは16.12ですリアクト)
マイケル・ウォレス

私は同じことを考えましたが、迅速な修正が必要だったので、強制更新を使用しました。
Charith Jayasanka

現実の世界では、それの用途があります。完璧なものはありません。ソフトウェアを公開したい場合は、他の誰かがソフトウェアを台無しにしたときに、物事を実現する方法をよく知っています。
Brain2000

1

これは、コンポーネントに小道具を追加し、ステートレスコンポーネントの親コンポーネントに状態を追加する場合、フックを明示的に使用せずに実行できます。

const ParentComponent = props => {
  const [updateNow, setUpdateNow] = useState(true)

  const updateFunc = () => {
    setUpdateNow(!updateNow)
  }

  const MyComponent = props => {
    return (<div> .... </div>)
  }

  const MyButtonComponent = props => {
    return (<div> <input type="button" onClick={props.updateFunc} />.... </div>)
  }

  return (
    <div> 
      <MyComponent updateMe={updateNow} />
      <MyButtonComponent updateFunc={updateFunc}/>
    </div>
  )
}

1

受け入れられた答えは良いです。理解しやすくするためだけに。

コンポーネントの例:

export default function MyComponent(props) {

    const [updateView, setUpdateView] = useState(0);

    return (
        <>
            <span style={{ display: "none" }}>{updateView}</span>
        </>
    );
}

再レンダリングを強制するには、以下のコードを呼び出します。

setUpdateView((updateView) => ++updateView);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.