ホームページのモバイル バージョンを構築しようとしていますが、ネストされたアコーディオンの「アイテム」にバグがあるようです。最初に開いたときに、下部のアイテム セクションの正しい高さが表示されません。
これを開くには、まずプロジェクト テキストをクリックします。次にプロジェクトがリストされ、次にプロジェクトをクリックしてプロジェクト カードを切り替えます。
(更新) これは、子アコーディオンを開いたときに親アコーディオンが高さを再更新していないために発生していると思います。
これを行う良い方法を知っていますか?それとも、必要に応じて、これを可能にする方法でコンポーネントを再構築する必要がありますか?難しいのは、Accordion が子を受け入れ、その中で Accordion を再利用しているため、非常に混乱していることです。コールバック関数を使用して親をトリガーできることはわかっていますが、その方法がよくわかりません。
ホーム.tsx
リーリーポートフォリオ.tsx
リーリーAccordionGroup.tsx - AccordionGroup の目的は、一度に 1 つの子 Accordion だけを開くことを許可することです。 Accordion が AccordionGroup に属していない場合は、独立して開いたり閉じたりできます。
リーリーAccordion.tsx
リーリープロジェクトカード.tsx
リーリーご協力いただければ幸いです。ありがとうございます!
P粉9981006482024-02-22 10:41:59
TL;DR: 親アコーディオンは、それに応じて高さを調整できるように、これらの変更について認識する必要があります。
「Create Lightweight React Accordions
」From Amin で示されているように、amiut/accordionify を使用していると思います。 A. レザプール。
これは、AccordionGroup
を使用する私が見つけた唯一のプロジェクトです。
アプリケーションのネストされたアコーディオン構造には親子関係があり、子アコーディオンの高さは展開されているか折りたたまれているかに応じて動的に変化します。
これは、AccordionGroup
コンポーネントに 配列に基づいて作成された複数の
Accordion コンポーネント プロジェクト
で説明できます。これらの が含まれる
Portfolio.tsxAccordion
コンポーネントは、前述の「子」アコーディオンです:
各子 Accordion
には、プロジェクトの詳細を表示する ProjectCard
が含まれています。ユーザーが Accordion
(または「プロジェクト」) をクリックすると、展開されて ProjectCard
が表示されます。
ここで高さの変更が関係します。アコーディオンはユーザー インタラクションに基づいて展開したり折りたたんだりして、高さを動的に変更します。
動的高さは Accordion.tsx
で管理されます:
handleToggle
関数が呼び出されると、アコーディオンが現在開いているかどうか (isOpen
) がチェックされます。そうである場合、高さは「0px」に設定されます(つまり、アコーディオンが折りたたまれています)。開いていない場合、高さはコンテンツのスクロールの高さに設定されます (つまり、アコーディオンが展開されます)。
これらの子供用アコーディオンの動的な高さの変化は、問題の重要な部分です。親アコーディオンは、それに応じて高さを調整できるように、これらの変更を認識する必要があります。
同じ Accordion.tsx
に次のように表示されます:
アコーディオンの高さは、アコーディオンが現在開いているかどうかを示す isActive
プロパティに従って設定されます。オンの場合、高さはアコーディオン コンテンツ (実質的に展開されたアコーディオン) のスクロールの高さに設定され、アクティブ化されていない場合、高さは 0px
(折りたたまれたアコーディオン) に設定されます。
ただし、このエフェクトは、独自の isActive
状態に基づいて各アコーディオンの高さを正しく調整しますが、子アコーディオンの高さの変化は考慮されません。
ネストされた (子) アコーディオンの高さが (展開または折りたたまれて) 変更される場合、親アコーディオンの高さ は再計算されないため、親の子の新しい高さに合わせて調整されません。 。
つまり、子アコーディオンの高さが変更されても、親アコーディオンは再レンダリングして高さを調整する必要があることを認識しません。ネストされたアコーディオンを展開または折りたたむときに再レンダリングが行われないと、親アコーディオンが正しい高さを表示しなくなります。###可能な解決策###
TL;DR: 解決策には、子アコーディオンの高さの変更を親に認識させ、それに応じて自身の高さを調整できるようにする必要があります。」(Josip Miskovic より)
Accordion コンポーネントは、
onHeightChange など、高さが変更されたときに呼び出されるコールバック関数 prop の恩恵を受けることができます。次に、
Portfolio コンポーネントで、# # を使用して新しいコールバック関数を
Accordion コンポーネントに渡すことで、この高さの変更を
Homepage コンポーネントまで反映できます。 #onHeightChange
プロパティ。
:
リーリー
次に、高さ変更イベントを伝播するように Portfolio コンポーネントを変更します。
最後に、高さ変更イベントがトリガーされたときに変更されるキーをホームページのポートフォリオ アコーディオンに追加できます。これにより、アコーディオンが再レンダリングされます:
リーリーこれにより、子 Accordion の高さが変更されるたびに、親 Accordion コンポーネントが強制的に再レンダリングされます。
P粉6499902732024-02-22 10:08:40
ご存知のとおり、ここでの実装は少し難しいです。なぜなら、祖父母アコーディオンの高さをその子アコーディオンから更新したい場合、そこから、対応するどの祖父母アコーディオンを更新したいのかを実際に知ることができないからです。 props 祖父母アコーディオンを与え、それを子アコーディオンに伝播できるように中間コンポーネント (例: Portfolio
、子アコーディオンの親) に props を渡します。
これを行うことで、祖父母と子供のアコーディオンが何らかの方法で通信できるようになります。
これが最善の解決策ではないかもしれませんが、残念ながらこれより良い解決策は思いつきません。
要約すると、アイデアは、各親アコーディオンの高さへの参照を保持する状態を最上位に作成することです。そのため、長さが「手動」で設定される配列となり、やや見苦しくなりますが、コンポーネントを動的に表示するためにデータ配列を使用する必要がある場合、これは問題にはなりません。後で説明するように、回避策の制限もわかります。
上で述べたように、まず HomePage コンポーネントに状態を作成します。
トップレベルで配列状態を作成した後、状態設定関数
setHeights、インデックス indexxx
、および対応する高さ heightParent
を各 Accordion に渡します。コンポーネントが親 Accordion の場合
リーリー
親に渡される indexx 属性と中間コンポーネント (ポートフォリオ) に渡される indexx
属性は、同じ値である必要があります。 は対応するインデックスを表し、実際にはこれが解決策の鍵となります。
将来の競合を避けるために、2 つの「x」を含む「indexx」という名前を付けました。
次に、受け取ったこれらの props を中間コンポーネントから子アコーディオンに渡します。
リーリー
これで、子 Accordion コンポーネントから、渡された
プロパティを利用して、HomePage 状態の対応する Accordion 親の高さを更新できるようになります。そのため、子の高さを更新すると、親高
リーリー最後に、Accordion の高さを指定するときに、それが親であることがわかるように、小道具として heightParent
を受け取るかどうかを確認できます。これにより、Accordion コンポーネントが
独自の状態 height
(親状態の場合) ではなく maxHeight
として、height
状態の更新が無視されるのはこのためです。は開いた親 Accordion なので、maxHeight
プロパティの設定方法を変更する必要があります。ここでは、Accordion の性質に応じて設定する必要があります。
リーリー
親アコーディオンが必要な場合は、その状態 height
を
リーリー
Accordion コンポーネントに
useEffect を追加し、受け取った
heightParent
height 状態を更新する必要がある場合にのみ実行します:
リーリー
上で述べたように、これはより理にかなっていて、最も美しいものですが、私は依然として最初の方法の方がシンプルで、
余分なレンダリングを節約できるので好みます。
動的データ処理: データを配列に保存し、これに基づいてコンポーネントを表示したい場合は、次のようにすることができます:
リーリー indexx
の代わりに使用できるように、親アコーディオンで key
を指定する必要があることがわかりますが、key
>この物件は特別なものであり、何があっても台無しにしたくありません。ご理解いただければ幸いです。
明らかに、この解決策は 1 つのレベルでのみ機能するため、サブ アコーディオン自体がサブ アコーディオンになった場合は、それを再度ラップする必要がありますが、何をしているのか理解していれば、おそらくこの状況には直面しないでしょう。あなたの実装では、子 Accordion は項目を表示する必要がありますが、いつか別の子 Accordion を返さなければならない日が来るか誰にもわかりません。そのため、私の提案は回避策であり、最善の解決策ではないと思います。
先ほども言いましたが、これは最善の解決策ではないかもしれませんが、正直に言うと、特にこの実装では、 このようなマルチレベルで実用的な解決策は存在するとは思いません。私が間違っていることを証明してください。 はい, この投稿をフォローしています。