🏎️

【NativeBase】Selectタグのアイテムを選択時に文字色を変更する + 解決アプローチ法

2022/05/11に公開約4,700字

React Nativeでの実装にあたり、UIライブラリとしてNativeBaseを使用しています。
その中でタイトルの通り躓いた箇所の解決法と、余談としてその解決に至った"解決までのアプローチ法"を共有します。

やりたいこと

Selectを開いて中身のItemを選択時に、文字色も変えたい。
(以下、公式例のコード)

https://docs.nativebase.io/select
const Example = () => {
  let [service, setService] = React.useState("");
  return <Center>
      <Box w="3/4" maxW="300">
        <Select 
	selectedValue={service} 
	minWidth="200" 
	accessibilityLabel="Choose Service" 
	placeholder="Choose Service" 
	_selectedItem={{
        bg: "teal.600",
        endIcon: <CheckIcon size="5" />
      }} mt={1} onValueChange={itemValue => setService(itemValue)}>
          <Select.Item label="UX Research" value="ux" />
          <Select.Item label="Web Development" value="web" />
          <Select.Item label="Cross Platform Development" value="cross" />
          <Select.Item label="UI Designing" value="ui" />
          <Select.Item label="Backend Development" value="backend" />
        </Select>
      </Box>
    </Center>;
};

Select内のアイテムを選択すると、上記_selectedItem内の記述が反映されて、以下のように背景色が付与されます。
これと同様に文字色も変更することが目的です。

試したこと

SelectのPropにcolorを指定すると以下画像のように文字色が変更できるので、同様に_selectedItem内にcolorを指定したらできるか...と思っていましたが上手くいきませんでした。

SelectにcolorのPropを指定した例

	<Select
	...
	_selectedItem={{
		bg: "teal.600",
		endIcon: <CheckIcon size="5" />,
	}}
	mt={1}
	onValueChange={(itemValue) => setService(itemValue)}
+	color={'red.400'}
        >

_selectedItemにcolorのPropを指定した例

	<Select
	...
	_selectedItem={{
		bg: "teal.600",
		endIcon: <CheckIcon size="5" />,
+		color:'red.400'
	}}
	mt={1}
	onValueChange={(itemValue) => setService(itemValue)}
        >

🤔 🤔 🤔

解決法

_selectedItem内で更に_textのPropとして渡す

_textのPropの中にcolorを指定することで、アイテムを選択時に指定した色に変更できます。

	<Select
	...
	_selectedItem={{
		bg: "teal.600",
		endIcon: <CheckIcon size="5" />,
+               _text : {
+                  color: "red.400",
+               },
	}}
	mt={1}
	onValueChange={(itemValue) => setService(itemValue)}
        >

公式ドキュメントのUtility Props -> Internal Propsに記載してある、Text childに渡す形式であればOKでした。

https://docs.nativebase.io/utility-props#h3-internal-props

またNativeBaseのDevComの方からも、テキストと見出し以外のコンポーネントでテキストのスタイルを変更する場合は、_textを使用して設定する必要があるとのことでした。

https://twitter.com/rohitistweet/status/1524242840427319297

無事に解決です。
お疲れ様でした🤗

余談:今回の課題解決までのアプローチの仕方

今回の例はUIライブラリの概念を理解していたり、NativeBase等UIライブラリを普段から使っていたらすぐに解決できるかもしれません。
しかしまだ使い倒せていなかったり、そもそもやりたいことに対して情報がドキュメントにもweb上にも共有されていなかった場合、解決法が迷子になってしまいます。

今回の例では、解決するのにGitHubにある元のライブラリのソースコードを紐解きました。

https://github.com/GeekyAnts/NativeBase

どのようなコードで成り立っていて、どのような仕組みで動いているか把握することで、一つ一つの流れを掴み最終的な目的の課題を解決することができます。
これは様々な場面で役に立つと思うので、今回はシンプルな例ですが「こんな風に考えたらいけるやん!」と課題解決の流れを掴める例として見てもらえると、いずれ役に立つのかなと思います。

今回の紐解き例

NativeBaseのSelectItemがどのような構造になっているか見る

やりたいことのゴールとしては、SelectItemに入っているテキストが選択時に色が変わることです。つまりテキストのカラーを指定するために、どこでどのようなPropを渡せば良いのか探りに行きます。

https://github.com/GeekyAnts/NativeBase/blob/9d67e8358fcf2e5e3970e239e42099265bcfb890/src/components/primitives/Select/SelectItem.tsx

SelectItemのコードを見てみると、Actionsheetを返しているようです。
次はこのActionsheetがどのようになっているか見にいきます。

NativeBaseのActionsheetがどのような構造になっているか見る

Actionsheetを見てみると、今度はButtonを返しています。

https://github.com/GeekyAnts/NativeBase/blob/9d67e8358fcf2e5e3970e239e42099265bcfb890/src/components/composites/Actionsheet/ActionsheetItem.tsx

次はButtonのコードを見ましょう。

NativeBaseのButtonがどのような構造になっているか見る

どうやらBoxの中にテキストが入ってそうですね。スタイリング関係はそのBoxのPropにある_textが何だか怪しそう。

https://github.com/GeekyAnts/NativeBase/blob/9d67e8358fcf2e5e3970e239e42099265bcfb890/src/components/primitives/Button/Button.tsx#L85-L112

そもそもButtonの文字色を変更する場合はどのようにするのか。ここで公式ドキュメントのButtonを見にいきます。

公式ドキュメントのButtonの項目を見る

https://docs.nativebase.io/button#h3-basic-with-ref

これだ🤯

Select.ItemButtonで構成されており、テキストの色を変更するにはその形に適したPropを渡してあげる必要があったということです。
つまり最初にやろうとしていたのは以下のようにButtonに直接colorのPropを渡していたので、機能していなかったんですね。

  return (
    <View style={styles.container}>
      <Button size="sm" variant={"solid"} px="3" color={'red.400'}>テスト</Button>
    </View>
  );

まとめ

困ったらまずソースコードとissueを見ることが大事...!
元のソースを見ること自体が中々ハードル高めに感じますが、「どのように動いているのかな」と見てみると案外すっと理解できたり、腑に落ちます。

何かしらお役に立てたら幸いです!

Discussion

ログインするとコメントできます