reactjs / reactjs/react.dev

[Suggestion]: Add note with some CSS selector side effects depending on DOM presence to `Activity` troubleshooting

オープン
#8,354 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

type: documentation
主要言語
JavaScript
スター
11.8k
フォーク
7.9k
平均マージ
1日 11時間
マージ済み PR(30日)
11

説明

Summary

Docs in Activity troubleshooting section,

My hidden components have unwanted side effects, lists <video>, <audio>, and <iframe> as common examples of side effects, but it does not yet cover the category of CSS selectors.

Some common CSS selectors, such as :has() and :is(), may continue to match after the content is hidden by <Activity>, leading to unexpected residual styles.

Page

https://react.dev/reference/react/Activity#troubleshooting

Details

Description

<Activity mode="hidden"> is designed to preserve DOM nodes (applying display: none), which is an intentional design choice. However, most CSS selectors only check the DOM structure and do not consider whether the element is actually visible.

This aligns with the existing explanation in the documentation:

"since a hidden component's DOM is not destroyed, any side effects from that DOM will persist, even after the component is hidden."

The persistent matching of CSS selectors is the exact same kind of DOM side effect, just occurring at the CSS layer,

But, docs doesn't have specific guidance for this type of CSS side effect on DOM. I have some problem to ask for suggestions:

  • Does the useLayoutEffect cleanup pattern mentioned in the docs for <video> also apply to handling this kind of CSS side effect?
  • Or is this a known limitation of the <Activity> design that should be explicitly stated in the documentation so developers are aware of it in advance?

Affected Selectors

:has()

/* ⚠️ Still applies after PageA is hidden by Activity */
body:has([data-has="a"]) .banner { background: red; }

:is() / :where()

/* ⚠️ Hidden elements are still matched, causing adjacent sibling styles to persist */
:is(section[data-sibling="a"]) ~ .footer { color: red; }
:where([data-page="a"]) .title { font-weight: bold; }

Demo

https://github.com/fufuShih/demo-react-activtiy-problem

The demo have two toggle modes (unmount / activity) and two page comps (A / B):

  • HasDemo: Uses body:has([data-has="a"]) .banner to detect if Page A is visible. After switching to Page B, the banner should revert to its default color.
  • SiblingDemo: Uses :is(section[data-sibling="a"]) ~ .footer to detect adjacent sibling elements. After switching to Page B, the footer should revert to its default color.

Both behave normally in unmount mode. However, when switched to activity mode, Page A is hidden by <Activity mode="hidden"> but remains in the DOM, causing both selectors to continue matching and preventing the styles from resetting.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

Activity のトラブルシューティングセクションとリンクされているデモリポジトリから始め、:has()、:is()、:where() の例と併せて、永続的な DOM の副作用について既存の説明を確認します。CSS セレクターのマッチングに関して想定されるガイダンスを確認し、その後、動作を説明する正確な注記と例を使ってトラブルシューティングドキュメントを更新します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
css, react
領域
documentation
issue の種類
ドキュメント
難易度
3/5
見積もり時間
1〜2日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
52/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。