コンテキストからのデータを使用してReactRe-Rendersを制御する方法

生きるために

サーバーからWebSocketで通知を受信するプロバイダーがあります。

export const MessageProvider: React.FC<ProviderProps> = ({ children }) => {
    const [state, dispatch] = useReducer(reducer, messageInitialState);

    useEffect(() => {
        let cancelled: boolean = false;
        __get(cancelled, undefined);
        return () => {
            cancelled = true;
        }
    }, []);
    useEffect(__wsEffect, []);

    const get = useCallback<(cancelled: boolean, userId: number | undefined) => Promise<void>>(__get, []);
    const put = useCallback<(message: Message) => Promise<void>>(__put, []);

    const value = { ...state, get, put };
    return (
        <MessageContext.Provider value={value}>
            {children}
        </MessageContext.Provider>
    )

    ...

    function __wsEffect() {
        log('{__wsEffect}', 'Connecting');
        let cancelled: boolean = false;
        const ws = newWebSocket(async (payload) => {
            if (cancelled) {
                return;
            }

            const message: Message = payload as Message;
            await storageSet(message, __key(message.id));
            dispatch({ actionState: ActionState.SUCCEEDED, actionType: ActionType.SAVE, data: message });
        });

        return () => {
            log('{__wsEffect} Disconnecting');
            cancelled = true;
            ws.close();
        }
    }
}

次に、コンポーネントで、次のようにこのコンテキストを使用します。

export const MessageListPage: React.FC<RouteComponentProps> = ({ history }) => {
    const { data, executing, actionType, actionError, get, put } = useContext(MessageContext);

    ...

    return (
        <IonPage id='MessageListPage'>
            <IonContent fullscreen>
                <IonLoading isOpen={executing && actionType === ActionType.GET} message='Fetching...' />
                {
                    !executing && !actionError && data && (
                        <div>
                            <IonList>
                                {
                                    groupBySender()
                                        .map(__data =>
                                            <div>
                                                <MessageListItem key={__data.sender} sender={__data.sender} messages={__data.messages} />
                                            </div>
                                        )
                                }
                            </IonList>
                        </div>
                    )
                }
            </IonContent>
        </IonPage>
    );
}

そして何が起こるかというとdata、コンテキストから更新されるたびに、このページが再レンダリングされ、すべてMessageListItemが再レンダリングされるようになります。

重要なのは、変更が影響を与える可能性のあるMessageListItemのみを再レンダリングしたいということです。これは可能ですか?useMemoとmemoを使うことを考えましたが、これらのオブジェクトを動的に作成しているので、その方法がわかりません。

これも可能ですか?

私は次のようなことを達成するよう努めています。

user a - x unread messages
user b - y unread messages
...

そして、ユーザーをクリックすると、アイテムが展開され、それらのメッセージが表示されます。しかし、通知を受け取ると、すべてがレンダリングされ、アイテムは展開されていない状態に戻ります。

アルマジュ

まったく同じ問題が発生しましたが、プロバイダーの子の再レンダリングを制御できないようです。React.memoコンテキスト値は小道具ではないため、上記のソリューションは機能しません。

この問題に対処する人気が高まっているnpmパッケージがあります:https//www.npmjs.com/package/react-tracked

この記事を読んで、より多くのオプションを入手できます:https//blog.axlight.com/posts/4-options-to-prevent-extra-rerenders-with-react-context/

私は個人的に、イベントリスナーとローカルストレージを備えたフックを使用して、を使用せずにグローバル状態にするための適切なコンポーネントの反応性を取得することになりましたuseContext

そんな感じ:

    import React, { createContext, useEffect, useState } from "react";
    import ReactDOM from "react-dom";

    type Settings = {
        foo?: string;
    }

    const useSettings = () => {
        let initialSettings: Settings = {
            foo: undefined
        };
        try {
            initialSettings = JSON.parse(localStorage.getItem("settings")) as Settings;
        } catch(e) {};

        const [settings, setSettings] = useState<Settings>(initialSettings);

        useEffect(() => {
            const listener = () => {
                if (localStorage.getItem("settings") !== JSON.stringify(settings)) {
                    try {
                        setSettings(JSON.parse(localStorage.getItem("settings")) as Settings);
                    } catch(e) {};
                }
            }

            window.addEventListener("storage", listener);
            return () => window.removeEventListener("storage", listener);
        }, []); 

        const setSettingsStorage = (newSettings: Settings) => {
            localStorage.setItem("settings", JSON.stringify(newSettings));
        }

        return [settings, setSettingsStorage];
    }

    const Content = () => {
        const [settings, setSettings] = useSettings();

        return <>Hello</>;
    }

    ReactDOM.render(
        <Content settings={{foo: "bar"}} />,
        document.getElementById("root")
    );

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

XMPPXMLを制御する方法

分類Dev

dust.jsを使用して現在のコンテキストからデータを取得する方法

分類Dev

Springコンテキストの初期化エラーを制御する方法

分類Dev

2つのクラス/デリゲートSwiftを使用して別のセルからUITableViewセルのコンテンツを制御する

分類Dev

SkSpriteNodeを使用してシーンキットのキャラクターの動きを制御する方法

分類Dev

forループを制御する方法は?

分類Dev

IEnumerableの更新を制御する方法

分類Dev

RollingUpdateの速度を制御する方法

分類Dev

filenoの出力を制御する方法は?

分類Dev

入力アラートダイアログからの空のテキストを処理し、アラートボタンを制御する方法

分類Dev

JavaでVLCを制御する方法

分類Dev

ASCII制御文字をgrepする方法

分類Dev

requestAnimationFrameでfpsを制御する方法は?

分類Dev

VisualBrush内でMediaElementを制御する方法

分類Dev

gnuplotでxticsを制御する方法

分類Dev

更新間隔を制御する方法

分類Dev

vlcjで音量を制御する方法は?

分類Dev

SignalでQProgressBarを制御する方法

分類Dev

制御文字を視覚化する方法

分類Dev

JavaScript で検証を制御する方法

分類Dev

Wordpressで<p>を制御する方法

分類Dev

%RANDOM%を制御する方法は?

分類Dev

Vuetify:vuetifyを使用してテキストコンポーネントのデータから多くのルールを追加することは可能ですか?

分類Dev

PHPを使用してAndroidデータパケットを制御する方法

分類Dev

ajaxリクエストでキャッシュ制御を制御する方法

分類Dev

1つの制御変数から複数の制御を生成する方法

分類Dev

C#を使用してUSBポートを制御する方法

分類Dev

ビットマスキングを使用して、あるテンソルから別のテンソルにデータをコピーする

分類Dev

JSON解析からのデータを表示し、Volley forNetworkを使用してオートコンプリートテキストに表示します

Related 関連記事

  1. 1

    XMPPXMLを制御する方法

  2. 2

    dust.jsを使用して現在のコンテキストからデータを取得する方法

  3. 3

    Springコンテキストの初期化エラーを制御する方法

  4. 4

    2つのクラス/デリゲートSwiftを使用して別のセルからUITableViewセルのコンテンツを制御する

  5. 5

    SkSpriteNodeを使用してシーンキットのキャラクターの動きを制御する方法

  6. 6

    forループを制御する方法は?

  7. 7

    IEnumerableの更新を制御する方法

  8. 8

    RollingUpdateの速度を制御する方法

  9. 9

    filenoの出力を制御する方法は?

  10. 10

    入力アラートダイアログからの空のテキストを処理し、アラートボタンを制御する方法

  11. 11

    JavaでVLCを制御する方法

  12. 12

    ASCII制御文字をgrepする方法

  13. 13

    requestAnimationFrameでfpsを制御する方法は?

  14. 14

    VisualBrush内でMediaElementを制御する方法

  15. 15

    gnuplotでxticsを制御する方法

  16. 16

    更新間隔を制御する方法

  17. 17

    vlcjで音量を制御する方法は?

  18. 18

    SignalでQProgressBarを制御する方法

  19. 19

    制御文字を視覚化する方法

  20. 20

    JavaScript で検証を制御する方法

  21. 21

    Wordpressで<p>を制御する方法

  22. 22

    %RANDOM%を制御する方法は?

  23. 23

    Vuetify:vuetifyを使用してテキストコンポーネントのデータから多くのルールを追加することは可能ですか?

  24. 24

    PHPを使用してAndroidデータパケットを制御する方法

  25. 25

    ajaxリクエストでキャッシュ制御を制御する方法

  26. 26

    1つの制御変数から複数の制御を生成する方法

  27. 27

    C#を使用してUSBポートを制御する方法

  28. 28

    ビットマスキングを使用して、あるテンソルから別のテンソルにデータをコピーする

  29. 29

    JSON解析からのデータを表示し、Volley forNetworkを使用してオートコンプリートテキストに表示します

ホットタグ

アーカイブ