SearchBar clear icon spreads a stray "key" prop into JSX, triggering a React dev warning

オープン 初心者向け
#4,035 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

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

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
76/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
静か
技術スタック
react, react-native, typescript

調査の方向性

src/searchbar/SearchBar-{ios,android,default}.tsx から始め、clear-icon の renderNode 呼び出しと、issue に示されているコンパイル済みの dist/searchbar ファイルを比較します。各 clear-icon props オブジェクトから不要な key フィールドを削除し、3 つの SearchBar バリアントがビルドされ、入力が空でない場合に React の開発警告が発生しなくなることを確認します。

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

説明

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch react-native-elements@3.4.3 for the project I'm working on.

Problem

All three SearchBar platform variants (SearchBar-ios, SearchBar-android, SearchBar-default) render the clear ("X") button via:

renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { key: 'cancel', onPress: this.clear }))

renderNode spreads this object directly into JSX (<Icon {...defaultProps} {...content} />), and since the object includes a literal key: 'cancel' field, this triggers React's dev-mode warning on every render where the clear icon is shown (i.e. whenever the search input is non-empty):

Warning: A props object containing a "key" prop is being spread into JSX:
  let props = {key: someKey, type: ..., name: ..., size: ..., color: ..., onPress: ...};
  <Themed.Icon {...props} />
React keys must be passed directly to JSX without using spread:
  let props = {type: ..., name: ..., size: ..., color: ..., onPress: ...};
  <Themed.Icon key={someKey} {...props} />

The key field serves no purpose here — Icon isn't part of a list, and React's JSX runtime strips key out of spread props before the component ever receives it in both dev and production builds (confirmed by inspecting react-jsx-runtime.production.js), so removing it doesn't change any behavior. It only silences this dev-mode-only warning.

In our case, this warning is surfaced by Expo Go/dev-client as an in-app error banner pinned to the bottom of the screen, which intermittently overlapped a bottom-pinned navigation button in our app and caused an automated end-to-end test to fail (the button briefly failed a strict visibility/hittability check while the banner was shown).

I also checked the rewritten @rneui/base package (currently v5.0.0) and the identical bug is present there too:

renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { key: 'cancel', onPress: handleClear }))

Here is the diff that solved my problem for react-native-elements@3.4.3:

diff --git a/dist/searchbar/SearchBar-android.js b/dist/searchbar/SearchBar-android.js
index fe25d36..58514da 100644
--- a/dist/searchbar/SearchBar-android.js
+++ b/dist/searchbar/SearchBar-android.js
@@ -113,7 +113,7 @@ class SearchBar extends Component {
             ])} rightIcon={<View style={{ flexDirection: 'row' }}>
               {showLoading && (<ActivityIndicator key="loading" style={StyleSheet.flatten([{ marginRight: 5 }, loadingStyle])} {...otherLoadingProps}/>)}
               {!isEmpty &&
-                    renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { key: 'cancel', onPress: this.clear }))}
+                    renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { onPress: this.clear }))}
             </View>} rightIconContainerStyle={StyleSheet.flatten([
                 styles.rightIconContainerStyle,
                 rightIconContainerStyle,
diff --git a/dist/searchbar/SearchBar-default.js b/dist/searchbar/SearchBar-default.js
index 6df7d17..13b9a8f 100644
--- a/dist/searchbar/SearchBar-default.js
+++ b/dist/searchbar/SearchBar-default.js
@@ -112,7 +112,7 @@ class SearchBar extends React.Component {
               {showLoading && (<ActivityIndicator key="loading" style={StyleSheet.flatten([{ marginRight: 5 }, loadingStyle])} {...otherLoadingProps}/>)}
 
               {!isEmpty &&
-                    renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { key: 'cancel', onPress: this.clear }))}
+                    renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { onPress: this.clear }))}
             </View>} rightIconContainerStyle={StyleSheet.flatten([
                 styles.rightIconContainerStyle,
                 rightIconContainerStyle,
diff --git a/dist/searchbar/SearchBar-ios.js b/dist/searchbar/SearchBar-ios.js
index 145206f..b2a385d 100644
--- a/dist/searchbar/SearchBar-ios.js
+++ b/dist/searchbar/SearchBar-ios.js
@@ -115,7 +115,7 @@ class SearchBar extends Component {
             ])} placeholderTextColor={placeholderTextColor || ((_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.colors) === null || _e === void 0 ? void 0 : _e.platform) === null || _f === void 0 ? void 0 : _f.ios) === null || _g === void 0 ? void 0 : _g.grey)} rightIcon={<View style={{ flexDirection: 'row' }}>
               {showLoading && (<ActivityIndicator key="loading" style={StyleSheet.flatten([{ marginRight: 5 }, loadingStyle])} {...otherLoadingProps}/>)}
               {!isEmpty &&
-                    renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { key: 'cancel', onPress: this.clear }))}
+                    renderNode(Icon, clearIcon, Object.assign(Object.assign({}, defaultClearIcon(theme)), { onPress: this.clear }))}
             </View>} rightIconContainerStyle={StyleSheet.flatten([
                 styles.rightIconContainerStyle,
                 rightIconContainerStyle,

(This is the compiled dist/ output for v3.4.3; the equivalent source is src/searchbar/SearchBar-{ios,android,default}.tsx, and the same fix likely applies to packages/base/src/searchbar/ on @rneui/base.)

This issue body was partially generated by patch-package.

主要言語
MDX
スター
25.9k
フォーク
4.7k
PR マージ指標
30日以内にマージされた PR はありません

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

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

はじめの一歩

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

react-native-elements/react-native-elements のほかの issue

react-native-elements/react-native-elements の issue をすべて見る

似ている issue

Web Dev の issue をもっと見る

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

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