react native typescript で redux を利用する。react hooks も利用

公式:https://reactnative.dev/docs/environment-setup を参考に redux の環境までを構築

  • macOS Big Sur
  • react native:0.64.1
  • react:17.0.1
  • typescript:3.8.3
省略
  • node, typescript, cocoapods の環境構築は省きます。

プロジェクト作成

npx react-native init AwesomeTSProject --template react-native-template-typescript

Metro サーバー起動

npx react-native start

アプリを実行

npx react-native run-ios

.prettier の設定

  • VScode の pritter 拡張機能Prettier - Code formatterはインストール済み
  • Code -> 基本設定 -> 設定   ワークスペース.vscode/settings.jsonの設定
{
    "files.trimTrailingWhitespace": true,
    "editor.tabSize": 2,
    "editor.insertSpaces": false,
    "editor.renderWhitespace": "all",
    // editor.formatOnSaveの代わりにsource.fixAll.eslintを使用するようになった
    "editor.formatOnSave": false,
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
    // デフォルト:prettier-vscode
    "editor.defaultFormatter": "esbenp.prettier-vscode",

    "eslint.workingDirectories": [{ "mode": "auto" }],
    "cSpell.ignoreRegExpList": [],
    "cSpell.userWords": [],
}

Redux の追加

yarn add redux react-redux clone
yarn add --dev @types/redux @types/react-redux @types/clone

ディレクトリ、ファイル作成

  • src ディレクトリを作成
  • App.tsx src ディレクトリへ移動 AwesomeTSProject/src/App.tsx
  • アクションのファイル、ストアのファイルを作成
    • AwesomeTSProject/src/AppAction.ts
    • AwesomeTSProject/src/Store.ts

Action Reducer を実装する

  • AwesomeTSProject/src/AppAction.ts に Action, Reducer を実装する。
import {Reducer} from 'redux';

// State
export interface AppState {
  verName: string;
  verCode: number;
}

// Action
type AppStateAction = {
  type: 'UPDATE_VERSION';
  payload: AppState;
};

// State の初期値
const initState: AppState = {
  verName: '1.0.0',
  verCode: 1,
};

/**
 * Reducer
 * @param state ステート
 * @param action アクション
 */
export const appReducer: Reducer<AppState, AppStateAction> = (
  state: AppState = initState,
  action: AppStateAction,
): AppState => {
  switch (action.type) {
    case 'UPDATE_VERSION': // バージョンを更新
      return {...state, ...action.payload};
    default:
      return state;
  }
};

Store を実装する

import {AppState, appReducer} from './AppAction';
import {combineReducers, createStore} from 'redux';

export interface RootState {
  app: AppState;
}

const reducers = combineReducers<RootState>({
  app: appReducer,
});

const store = createStore(reducers);

export default store;

App.tsx に Provider を設定

const App = () => {
  const isDarkMode = useColorScheme() === 'dark';

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };

  return (
    <Provider store={store}>
      <SafeAreaView style={backgroundStyle}>
        <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
        <ScrollView
          contentInsetAdjustmentBehavior="automatic"
          style={backgroundStyle}>
          {/* ここのSectionのなかでstateを使ってみる */}
          <Section />
        </ScrollView>
      </SafeAreaView>
    </Provider>
  );
};

useSelector で AppState を取得する

const Section: React.FC = () => {
  // AppState を取得
  const appState = useSelector<RootState, AppState>(s => s.app);
  // verName, verCode を取り出す
  const {verName, verCode} = appState;
  return (
    <View style={styles.sectionContainer}>
      <Text style={[styles.sectionDescription]}>{`version: ${verName}`}</Text>
      <Text
        style={[styles.sectionDescription]}>{`versionCode: ${verCode}`}</Text>
    </View>
  );
};

サンプルソース

https://github.com/ka-yamao/AwesomeTSProject