React ネストされたアコーディオンの親の高さが更新されない
P粉293341969
P粉293341969 2024-02-21 15:55:48
0
2
337

ホームページのモバイル バージョンを構築しようとしていますが、ネストされたアコーディオンの「アイテム」にバグがあるようです。最初に開いたときに、下部のアイテム セクションの正しい高さが表示されません。

これを開くには、まずプロジェクト テキストをクリックします。次にプロジェクトがリストされ、次にプロジェクトをクリックしてプロジェクト カードを切り替えます。

(更新) これは、子アコーディオンを開いたときに親アコーディオンが高さを再更新していないために発生していると思います。

これを行う良い方法を知っていますか?それとも、必要に応じて、これを可能にする方法でコンポーネントを再構築する必要がありますか?難しいのは、Accordion が子を受け入れ、その中で Accordion を再利用しているため、非常に混乱していることです。コールバック関数を使用して親をトリガーできることはわかっていますが、その方法がよくわかりません。

ホーム.tsx

リーリー

ポートフォリオ.tsx

リーリー

AccordionGroup.tsx - AccordionGroup の目的は、一度に 1 つの子 Accordion だけを開くことを許可することです。 Accordion が AccordionGroup に属していない場合は、独立して開いたり閉じたりできます。

リーリー

Accordion.tsx

リーリー

プロジェクトカード.tsx

リーリー

ご協力いただければ幸いです。ありがとうございます!

P粉293341969
P粉293341969

全員に返信(2)
P粉998100648

問題分析:

TL;DR: 親アコーディオンは、それに応じて高さを調整できるように、これらの変更について認識する必要があります。

Create Lightweight React Accordions」From Amin で示されているように、amiut/accordionify を使用していると思います。 A. レザプール
これは、AccordionGroup を使用する私が見つけた唯一のプロジェクトです。

アプリケーションのネストされたアコーディオン構造には親子関係があり、子アコーディオンの高さは展開されているか折りたたまれているかに応じて動的に変化します。

これは、AccordionGroup コンポーネントに 配列に基づいて作成された複数の Accordion コンポーネント プロジェクト が含まれる Portfolio.tsx で説明できます。これらの Accordion コンポーネントは、前述の「子」アコーディオンです:

リーリー

各子 Accordion には、プロジェクトの詳細を表示する ProjectCard が含まれています。ユーザーが Accordion (または「プロジェクト」) をクリックすると、展開されて ProjectCard が表示されます。
ここで高さの変更が関係します。アコーディオンはユーザー インタラクションに基づいて展開したり折りたたんだりして、高さを動的に変更します。

動的高さは Accordion.tsx で管理されます:

リーリー

handleToggle 関数が呼び出されると、アコーディオンが現在開いているかどうか (isOpen) がチェックされます。そうである場合、高さは「0px」に設定されます(つまり、アコーディオンが折りたたまれています)。開いていない場合、高さはコンテンツのスクロールの高さに設定されます (つまり、アコーディオンが展開されます)。

これらの子供用アコーディオンの動的な高さの変化は、問題の重要な部分です。親アコーディオンは、それに応じて高さを調整できるように、これらの変更を認識する必要があります。

同じ Accordion.tsx に次のように表示されます:

リーリー

アコーディオンの高さは、アコーディオンが現在開いているかどうかを示す isActive プロパティに従って設定されます。オンの場合、高さはアコーディオン コンテンツ (実質的に展開されたアコーディオン) のスクロールの高さに設定され、アクティブ化されていない場合、高さは 0px (折りたたまれたアコーディオン) に設定されます。

ただし、このエフェクトは、独自の isActive 状態に基づいて各アコーディオンの高さを正しく調整しますが、子アコーディオンの高さの変化は考慮されません。

ネストされた (子) アコーディオンの高さが (展開または折りたたまれて) 変更される場合、親アコーディオンの高さ は再計算されないため、親の子の新しい高さに合わせて調整されません。 。

つまり、子アコーディオンの高さが変更されても、親アコーディオンは再レンダリングして高さを調整する必要があることを認識しません。ネストされたアコーディオンを展開または折りたたむときに再レンダリングが行われないと、親アコーディオンが正しい高さを表示しなくなります。

###可能な解決策###

TL;DR: 解決策には、子アコーディオンの高さの変更を親に認識させ、それに応じて自身の高さを調整できるようにする必要があります。

(「

React: Force コンポーネントの再レンダリングで言及されているテクニックの 1 つ | 4 つの簡単な方法

」(Josip Miskovic より)

Accordion コンポーネントは、onHeightChange など、高さが変更されたときに呼び出されるコールバック関数 prop の恩恵を受けることができます。次に、Portfolio コンポーネントで、# # を使用して新しいコールバック関数を Accordion コンポーネントに渡すことで、この高さの変更を Homepage コンポーネントまで反映できます。 #onHeightChange プロパティ。

accordion.tsx

: リーリー 次に、高さ変更イベントを伝播するように Portfolio コンポーネントを変更します。

リーリー

最後に、高さ変更イベントがトリガーされたときに変更されるキーをホームページのポートフォリオ アコーディオンに追加できます。これにより、アコーディオンが再レンダリングされます:

リーリー

これにより、子 Accordion の高さが変更されるたびに、親 Accordion コンポーネントが強制的に再レン​​ダリングされます。

いいねを押す +0
P粉649990273

ご存知のとおり、ここでの実装は少し難しいです。なぜなら、祖父母アコーディオンの高さをその子アコーディオンから更新したい場合、そこから、対応するどの祖父母アコーディオンを更新したいのかを実際に知ることができないからです。 props 祖父母アコーディオンを与え、それを子アコーディオンに伝播できるように中間コンポーネント (例: Portfolio、子アコーディオンの親) に props を渡します。
これを行うことで、祖父母と子供のアコーディオンが何らかの方法で通信できるようになります。
これが最善の解決策ではないかもしれませんが、残念ながらこれより良い解決策は思いつきません。


要約すると、アイデアは、各親アコーディオンの高さへの参照を保持する状態を最上位に作成することです。そのため、長さが「手動」で設定される配列となり、やや見苦しくなりますが、コンポーネントを動的に表示するためにデータ配列を使用する必要がある場合、これは問題にはなりません。後で説明するように、回避策の制限もわかります。


###解決:###

次に、質問に含まれている内容に対して機能する、最もシンプルで簡単な修正を行っていきます。


上で述べたように、まず HomePage コンポーネントに状態を作成します。

リーリー

トップレベルで配列状態を作成した後、状態設定関数

setHeights

、インデックス indexxx、および対応する高さ heightParent を各 Accordion に渡します。コンポーネントが親 Accordion の場合 リーリー

注:

親に渡される indexx 属性と中間コンポーネント (ポートフォリオ) に渡される indexx 属性は、同じ値である必要があります。 は対応するインデックスを表し、実際にはこれが解決策の鍵となります。 将来の競合を避けるために、2 つの「x」を含む「indexx」という名前を付けました。 次に、受け取ったこれらの props を中間コンポーネントから子アコーディオンに渡します。 リーリー
これで、子 Accordion コンポーネントから、渡された

indexx

プロパティを利用して、HomePage 状態の対応する Accordion 親の高さを更新できるようになります。そのため、子の高さを更新すると、親高

リーリー

最後に、Accordion の高さを指定するときに、それが親であることがわかるように、小道具として heightParent を受け取るかどうかを確認できます。これにより、Accordion コンポーネントが

を使用するようになります。 heightParent

独自の状態 height (親状態の場合) ではなく maxHeight として、height 状態の更新が無視されるのはこのためです。は開いた親 Accordion なので、maxHeight プロパティの設定方法を変更する必要があります。ここでは、Accordion の性質に応じて設定する必要があります。 リーリー 親アコーディオンが必要な場合は、その状態 height

maxHeight
として使用し、コードを同じに保つ方が合理的です

リーリー Accordion コンポーネントに useEffect を追加し、受け取った heightParent

プロパティが更新および定義された場合にのみ実行されるようにすることで、これを行うこともできます。これは、コード 親アコーディオンが

height 状態を更新する必要がある場合にのみ実行します: リーリー 上で述べたように、これはより理にかなっていて、最も美しいものですが、私は依然として最初の方法の方がシンプルで、余分なレンダリングを節約できるので好みます

動的データ処理: データを配列に保存し、これに基づいてコンポーネントを表示したい場合は、次のようにすることができます:

リーリー

indexx の代わりに使用できるように、親アコーディオンで key を指定する必要があることがわかりますが、key >この物件は特別なものであり、何があっても台無しにしたくありません。ご理解いただければ幸いです。


制限:

明らかに、この解決策は 1 つのレベルでのみ機能するため、サブ アコーディオン自体がサブ アコーディオンになった場合は、それを再度ラップする必要がありますが、何をしているのか理解していれば、おそらくこの状況には直面しないでしょう。あなたの実装では、子 Accordion は項目を表示する必要がありますが、いつか別の子 Accordion を返さなければならない日が来るか誰にもわかりません。そのため、私の提案は回避策であり、最善の解決策ではないと思います。


先ほども言いましたが、これは最善の解決策ではないかもしれませんが、正直に言うと、特にこの実装では、 このようなマルチレベルで実用的な解決策は存在するとは思いません。私が間違っていることを証明してください。 はい, この投稿をフォローしています。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート