準備
shell
npm i recoil
shell
mkdir -p lib/states/{atoms,selectors}
App.tsx で、 RecoilRoot でコンポーネントを囲む
App.tsx
import CTBottomNavigation from './components/CTBottomNavigation';
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { Provider as PaperProvider } from 'react-native-paper';
import { enGB, registerTranslation } from 'react-native-paper-dates';
import { RecoilRoot } from 'recoil';
import 'reflect-metadata';
export default function App() {
registerTranslation('en', enGB);
return (
<PaperProvider>
<RecoilRoot>
<CTBottomNavigation />
</RecoilRoot>
<StatusBar style="auto" />
</PaperProvider>
);
}
ユースケース
Recoil を使用する想定ケースです。
ボトムナビゲーションのインデックスを Recoil で管理する
ボトムナビゲーションの値が変更されたタイミングで、値をリロードしたケースがありました。
親コンポーネントのメニューから、描画されるスクリーンに対して、 props
で navigationIndex
を渡していましたが、 Recoil でグローバルで管理することで、いちいち navigationIndex
を渡さなくても良くなりました。
元々は以下のように props
で bottomNavigationIndex
を渡して、 bottomNavigationIndex
が更新されたタイミングで再ロードするような処理を書いていました。
component.tsx
interface CTAgendaProps {
bottomNavigationIndex: number;
}
const CTAgenda: React.FC<CTAgendaProps> = ({ bottomNavigationIndex }) => {
useEffect(() => {}, [bottomNavigationIndex])
}
このような props
で bottomNavigationIndex
を渡すのをやめて、 Recoil 経由で渡せるようにしたいです。
atom を作成する
lib/states/atoms/BottomNavigationIndexState.ts
import { atom } from "recoil";
export const BottomNavigationIndexState = atom({
key: 'bottomNavigationIndexState',
default: 0,
})
ナビゲーションのインデックスの変更を Recoil で管理する
NavigationSample.tsx
const SampleBottomNavigation = () => {
const [bottomNavigationIndex, setBottomNavigationIndex] = useRecoilState(
BottomNavigationIndexState
);
const onIndexChange = (index: number) => {
setBottomNavigationIndex(index);
};
return (
<BottomNavigation
navigationState={{ index: bottomNavigationIndex, routes }}
onIndexChange={onIndexChange}
renderScene={renderScene}
/>
)
}
Recoil から状態を取得する
AnalysisScreen.tsx
import {
ANALYSIS_SCREEN_INDEX,
BottomNavigationIndexState,
} from '../../lib/states/atoms/BottomNavigationIndexState';
import MonthlyExpense from '../MonthlyExpense';
import React, { useEffect } from 'react';
import { SafeAreaView, ScrollView, StyleSheet } from 'react-native';
import { useRecoilValue } from 'recoil';
export default function AnalysisScreen() {
const bottomNavigationIndex = useRecoilValue(BottomNavigationIndexState);
useEffect(() => {
if (bottomNavigationIndex !== ANALYSIS_SCREEN_INDEX) {
return;
}
console.log(`bottomNavigationIndex: ${bottomNavigationIndex}`);
}, [bottomNavigationIndex]);
return (
<SafeAreaView style={styles.container}>
<ScrollView>
<MonthlyExpense />
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginHorizontal: 10,
},
});
Recoil から状態を取得して、自分のスクリーンが開かれたときに何か処理を行うようにしています。