ReactNativeアプリでのReduxの使用の概要
序章
Redux は、JavaScriptアプリの予測可能な状態コンテナーです。 Reduxを初めて使用する場合は、Reduxの紹介を参照することをお勧めします。
この記事では、ReactNativeアプリケーションでReduxを使用してユーザーデータを永続化する方法を学習します。 このアプリケーションは、接続されている友達の数を表示するHomeScreen
と、追加する可能性のある友達のリストを表示するFriendsScreen
を備えた模擬ソーシャルネットワークです。 Reduxを使用して、2つの画面間で状態を共有します。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- Node.jsのローカル開発環境。 Node.jsをインストールしてローカル開発環境を作成する方法に従ってください。
- 新しいReactNativeプロジェクトを作成するための環境のセットアップと、iOSまたはAndroidシミュレーターの使用に精通していると役立つ場合があります。
このチュートリアルは、 ReactNativeでReactNavigationでルーティングを使用する方法で説明されているトピックに基づいています。 プロジェクトがどのように機能するかについての詳細は、このチュートリアルを読むことをお勧めしますが、必須ではありません。
このチュートリアルは、ノードv14.7.0、npm
v6.14.7、react
v16.13.1、react-native
v0.63.2、@react-navigation/native
v5.7.3、 @react-navigation/stack
v5.9.0、redux
v4.0.5、およびreact-redux
v7.2.1。
ステップ1—プロジェクトのセットアップとインストールRedux
このチュートリアルでは、 ReactNativeでReactNavigationでルーティングを使用する方法のコードの修正バージョンを使用します。 開始するには、MySocialNetworkのクローンを作成します。
- git clone https://github.com/do-community/MySocialNetwork.git
次に、プロジェクトディレクトリに移動します。
- cd MySocialNetwork
gitブランチをredux-starter
に変更します。
- git checkout redux-starter
次に、プロジェクトの依存関係をインストールします。
- npm install
次に、redux
およびreact-redux
ライブラリをプロジェクトにインストールします。
- npm install redux@4.0.5 react-redux@7.2.1
これでプロジェクトがセットアップされ、依存関係がインストールされました。
ステップ2—レデューサーを作成する
Reduxをアプリに接続するには、レデューサーとアクションを作成する必要があります。
まず、友達レデューサーを作成します。 レデューサーは、前の状態とアクションを引数として取り、新しい状態を返す純粋関数です。 レデューサーは、変更に応じてアプリ全体で友達の現在の状態を最新の状態に保つのに役立ちます。
プロジェクトのルートレベルでFriendsReducer.js
ファイルを作成します。
- nano FriendsReducer.js
次のコードを追加します。
import { combineReducers } from 'redux';
const INITIAL_STATE = {
current: [],
possible: [
'Alice',
'Bob',
'Sammy',
],
};
const friendsReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
default:
return state
}
};
export default combineReducers({
friends: friendsReducer
});
このファイルでは、ソーシャルネットワークに追加する可能性のある友達と一緒にINITIAL_STATE
変数を作成します。 次に、friendsReducer
をfriends
というプロパティとしてエクスポートします。
レデューサーを配置したら、友達を追加する方法が必要になります。
ステップ3—アクションを作成する
アクションは、アプリケーションからRedux
ストアにデータを送信する情報のペイロードを表すJavaScriptオブジェクトです。
アクションには、タイプとオプションのペイロードがあります。 このチュートリアルでは、タイプはADD_FRIEND
になり、ペイロードはcurrent
フレンズ配列に追加するフレンズの配列インデックスになります。
プロジェクトのルートレベルでFriendsActions.js
ファイルを作成します。
- nano FriendsActions.js
addFriend
を追加します:
export const addFriend = friendsIndex => (
{
type: 'ADD_FRIEND',
payload: friendsIndex,
}
);
ユーザーが友達をクリックすると、このコードはfriends.possible
配列からfriendsIndex
を取得します。 次に、そのインデックスを使用して、このフレンドをfriends.current
アレイに移動する必要があります。
FriendsReducer.js
に再度アクセスしてください:
- nano FriendsReducer.js
ADD_FRIEND
を追加します:
// ...
const friendsReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case 'ADD_FRIEND':
// Pulls current and possible out of previous state
// We do not want to alter state directly in case
// another action is altering it at the same time
const {
current,
possible,
} = state;
// Pull friend out of friends.possible
// Note that action.payload === friendIndex
const addedFriend = possible.splice(action.payload, 1);
// And put friend in friends.current
current.push(addedFriend);
// Finally, update the redux state
const newState = { current, possible };
return newState;
default:
return state
}
};
// ...
このコードは、現在の友達と可能性のある友達を以前の状態から引き出します。 Array.splice()
は、可能な友達の配列から友達を取得します。 Array.push
は、現在の友達の配列に友達を追加します。 変更が加えられると、状態が更新されます。
これで、レデューサーとアクションができました。 レデューサーをアプリに適用する必要があります。
ステップ4—アプリにレデューサーを追加する
React Reduxのプロバイダーコンポーネントを使用して、アプリのfriends
状態を提供する必要があります。
App.js
を開きます:
- nano App.js
Provider
、createStore
、およびfriendsReducer
をインポートします。
import 'react-native-gesture-handler';
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import friendsReducer from './FriendsReducer';
import HomeScreen from './HomeScreen';
import FriendsScreen from './FriendsScreen';
// ...
強調表示されたコードを追加して、createStore
およびProvider
に置き換えます。
// ...
const store = createStore(friendsReducer);
class App extends React.Component {
// ...
render() {
return (
<Provider store={store}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
<Stack.Screen
name="Friends"
component={FriendsScreen}
/>
</Stack.Navigator>
</NavigationContainer>
</Provider>
)
}
}
これで、アプリ内でfriends
にアクセスできますが、HomeScreen
およびFriendsScreen
に追加する必要があります。
ステップ5—画面にReduxを追加する
このステップでは、mapStateToProps
機能を使用して、画面からfriends
にアクセスできるようにします。 この関数は、2つの画面でstate
をFriendsReducer
からprops
にマップします。
HomeScreen.js
から始めましょう。 HomeScreen.js
ファイルを開きます。
- nano HomeScreen.js
HomeScreen.js
で強調表示されているコード行を追加して置き換えます。
import React from 'react';
import { connect } from 'react-redux';
import { StyleSheet, Text, View, Button } from 'react-native';
class HomeScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>You have (undefined) friends.</Text>
<Button
title="Add some friends"
onPress={() =>
this.props.navigation.navigate('Friends')
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
const mapStateToProps = (state) => {
const { friends } = state
return { friends }
};
export default connect(mapStateToProps)(HomeScreen);
このコード変更により、react-redux
が追加され、friends
がHomeScreen
で使用できるようになります。
次に、現在の友達の値を追加します(this.props.friends.current
):
class HomeScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>You have { this.props.friends.current.length } friends.</Text>
<Button
title="Add some friends"
onPress={() =>
this.props.navigation.navigate('Friends')
}
/>
</View>
);
}
}
HomeScreen
に現在の友達の数が表示されます。 これで、FriendsScreen
に進むことができます。
FriendsScreen.js
を開きます:
- nano FriendsScreen.js
FriendsScreen.js
で強調表示されているコード行を追加して置き換えます。
import React from 'react';
import { connect } from 'react-redux';
import { StyleSheet, Text, View, Button } from 'react-native';
class FriendsScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Add friends here!</Text>
<Button
title="Back to home"
onPress={() =>
this.props.navigation.navigate('Home')
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
const mapStateToProps = (state) => {
const { friends } = state
return { friends }
};
export default connect(mapStateToProps)(FriendsScreen);
このコード変更により、react-redux
が追加され、friends
がFriendsScreen
で使用できるようになります。
可能な友達の値を追加します(props.friends.possible
):
class FriendsScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Add friends here!</Text>
{
this.props.friends.possible.map((friend, index) => (
<Button
key={ friend }
title={ `Add ${ friend }` }
/>
))
}
<Button
title="Back to home"
onPress={() =>
this.props.navigation.navigate('Home')
}
/>
</View>
);
}
}
FriendsScreen
に移動すると、レデューサーからのすべての可能な友達が表示されます。
最後に、新しいReduxaddFriend
アクションをFriendsScreen.js
に追加します。
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { StyleSheet, Text, View, Button } from 'react-native';
import { addFriend } from './FriendsActions';
class FriendsScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Add friends here!</Text>
{
this.props.friends.possible.map((friend, index) => (
<Button
key={ friend }
title={ `Add ${ friend }` }
onPress={() =>
this.props.addFriend(index)
}
/>
))
}
<Button
title="Back to home"
onPress={() =>
this.props.navigation.navigate('Home')
}
/>
</View>
);
}
}
// ...
const mapDispatchToProps = dispatch => (
bindActionCreators({
addFriend,
}, dispatch)
);
export default connect(mapStateToProps, mapDispatchToProps)(FriendsScreen);
ソーシャルネットワークに2人の友達を追加し、HomeScreen
に戻って、ユーザーの現在の友達の数を確認しましょう。
これで、すべてのロジックがApp.js
からRedux
に移動しました。これにより、特に認証やデータベース統合などのページや機能を追加するときに、アプリがはるかに柔軟になります。
まとめる前に、コードをクリーンアップしましょう。
ステップ6—クリーンアップ
Redux
を使用しているので、App.js
から渡した小道具は不要になります。
action
タイプを別のファイルに保存することで、さらにクリーンアップすることができます。
文字列'ADD_FRIEND'
を、action
とその友人reducer
の2か所で使用しています。 これは危険です。文字列を一方の場所で変更し、もう一方の場所では変更しないと、アプリケーションが破損する可能性があるためです。 アプリが大きくなるにつれて、これらすべてのaction
タイプをtypes.js
というファイルに保持するのが理にかなっています。
ルートレベルでtypes.js
ファイルを作成します。
- nano types.js
次のコードを追加します。
export const ADD_FRIEND = 'ADD_FRIEND';
次に、FriendsActions.js
に再度アクセスして、新しいADD_FRIEND
を使用します。
nano FriendsActions.js
引用符で囲まれた'ADD_FRIEND'
をaction
の変数ADD_FRIEND
に変更します。
import { ADD_FRIEND } from './types';
export const addFriend = friendsIndex => (
{
type: ADD_FRIEND,
payload: friendsIndex,
}
);
次に、FriendsReducer.js
に再度アクセスして、新しいADD_FRIEND
も使用します。
- nano FriendsReducer.js
引用符で囲まれた'ADD_FRIEND'
をreducer
の変数ADD_FRIEND
に変更します。
import { combineReducers } from 'redux';
import { ADD_FRIEND } from './types';
// ...
const friendsReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case ADD_FRIEND:
// ...
default:
return state;
}
};
これにより、アプリケーションの脆弱性が低下します。 アプリケーションを開発するときは、コードを統合し、自分自身を繰り返さないようにする機会に注意する必要があります。
結論
このチュートリアルでは、redux
、reducers
、actions
、およびスケーラブルなデータ管理について説明しました。
データをデータベースと同期させることから、認証やユーザー権限の追跡まで、Reduxでできることはもっとたくさんあります。
このチュートリアルの完全なソースコードは、GitHubで入手できます。
Reactの詳細については、 React.js シリーズのコーディング方法をご覧になるか、Reactトピックページで演習やプログラミングプロジェクトを確認してください。