react-native-elementsで動的にThemeを変更する
2019-02-14

react-native-elementsで動的にThemeを変更する

react-nativeプロダクトでベースとなるUIコンポーネントライブラリを探していたら、ちょうどいいタイミングで
react-native-elementsがv1になったので使ってみることにしました。

v1の目玉機能の一つにThemeがあります。
基本的な使い方は、自身でカスタムThemeを作成してからThemeProviderにそのThemeを渡すだけで動くのですが、一度設定したThemeをプログラムにて変更する場合に一癖あったので、その辺りを紹介します。

Themeについての公式のドキュメントはこちらです。

Themeの基本的な使い方

まずカスタムThemeを作成します。Themeのオブジェクトフォーマットについてはこちらを参照してください。

const theme = {
  colors: {
    primary: 'green'
  }
};

これをApp.jsなどの上位のコンポーネントにThemeProviderを置いてThemeを設定して読み込ませれば大丈夫です。

// App.js

  ...

  render() {
    return (
      <ThemeProvider theme={theme}>
        <AppRoute /> // react-native-router-fluxなどのRoute設定コンポーネント
      </ThemeProvider>
    );
  }

Themeを動的に変更する

さて、Themeを動的に変更してみましょう。ThemeProviderthemeをpropsに持っているので、これを変更すればThemeも変更できそうですが、実際には変更できません。

- Question: Is it possible to toggle active Theme at runtime? · Issue #1714 · react-native-training/react-native-elements

propsでのThemeの変更をゆるしてしまった場合、全てのコンポーネントツリーのコンポーネントが再描画されてしまうため、これを避けるためにwithTheme HOC(High Order Component)かThemeConsumerを使ってupdateThemeを呼び出す必要があるようです。

今回はwithThemeを使ってみました。

withThemeを使ったThemeの変更

まずThemeの変更をトリガーするコンポーネントをwithThemeでラップします。ラップされたコンポーネントにはpropsにupdatethemethemeが渡されてくるので、updateThemeに変更後のThemeを設定します。

// Child.js
const Child = (props) => {
  return (
    <View>
      <Button
        title="Change theme"
        onPress={() => props.updateTheme({ colors: { primary: 'blue' }})}
      />
    </View>
  );
} 

export default withTheme(Child);

実際の画面はこんな感じで切り替わります。