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