あまりサンプルが無いので自分用にメモ。
根本を理解していないのでズレてるかも(でも期待の動作はします)。
動作イメージ
下記のような感じ。Settingsで値いじったら、その他の画面にも反映・利用できるようにしたい。
ユーザープロファイルを引き回すイメージなので、name変数とそれを変更するupdateName()を引き回す。
ディレクトリ構造
とりあえずRedux-way風。いまいち落ち着かない。
以下、実装を見ていきます。
環境
expを利用しますが、create-react-native-appでも基本同じかと。
exp init demo
cd demo
npm install --save redux react-redux react-navigation
npm install
実装
App.js
まずはApp.js。基本的な流れをわかりやすく?するために、tab, stack, storeの紐づけを書いている。
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import createStore from './createStore';
//screens
import HomeScreen from './screens/HomeScreen';
import AboutScreen from './screens/AboutScreen';
import SettingsScreen from './screens/SettingsScreen';
//store
const store = createStore();
//stack
const Stack = createStackNavigator(
{
Home: HomeScreen,
About: AboutScreen,
},
{
initialRouteName: 'Home',
}
);
//tabs
const Tabs = createBottomTabNavigator(
{
Top: Stack,
Settings: SettingsScreen
}
);
//main
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Tabs/>
</Provider>
);
}
}
createStore.js
今回はuser情報のみを扱うので本当はuserReducerだけあればいい。stackやnavの初期値を引き回すサンプルもあるけど、今ひとつ意味がわからないので放って置く。設定せずとも独自の値は引き回せる。
import { createStore as reduxCreateStore, combineReducers, compose, applyMiddleware } from "redux";
import { stackReducer } from "./reducers/stackReducer";
import { tabReducer } from "./reducers/tabReducer";
import userReducer from "./reducers/userReducer";
export default function createStore(){
const store = reduxCreateStore(
combineReducers({
stack: stackReducer,
tab: tabReducer,
user: userReducer
}),
);
return store;
}
HomeScreen.js
ただ表示しているだけ。
import React from 'react';
import { Button, View, Text } from 'react-native';
import { connect } from 'react-redux';
import { updateName } from '../actions/userAction';
class HomeScreen extends React.Component {
render() {
// console.log(this.props);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home</Text>
<Button
title='Link to About'
onPress={() => this.props.navigation.navigate('About')}
/>
<Text>{this.props.user.name}</Text>
</View>
);
}
}
const mapStateToProps = state => ({
user: state.user
});
const mapDispatchToProps = dispatch => {
return {
updateName: (name) => dispatch(updateName(name))
}
}
export default connect(mapStateToProps,mapDispatchToProps)(HomeScreen);
// export default HomeScreen;
AboutScreen.js
ただ表示してるだけ。いちおうボタンつけて値(名前)をAboutでも更新できるようにしてみた。
import React from 'react';
import { Button, View, Text } from 'react-native';
import { connect } from 'react-redux';
import { updateName } from '../actions/userAction';
class AboutScreen extends React.Component {
render() {
// console.log(this.props);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>About</Text>
<Text>{this.props.user.name}</Text>
<Button
title='名前の変更'
onPress={()=>this.props.updateName('yamada@about')}
/>
</View>
);
}
}
const mapStateToProps = state => ({
user: state.user
});
const mapDispatchToProps = dispatch => {
return {
updateName: (name) => dispatch(updateName(name))
}
}
export default connect(mapStateToProps,mapDispatchToProps)(AboutScreen);
// export default AboutScreen;
SettingsScreen.js
値の表示と変更用のボタン。
import React from 'react';
import { Button, View, Text } from 'react-native';
import { connect } from 'react-redux';
import { updateName } from '../actions/userAction';
class SettingsScreen extends React.Component {
render() {
// console.log(this.props);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Settings</Text>
<Text>{this.props.user.name}</Text>
<Button
title='名前の変更'
onPress={()=>this.props.updateName('suzuki@settings')}
/>
</View>
);
}
}
const mapStateToProps = state => ({
user: state.user
});
const mapDispatchToProps = dispatch => {
return {
updateName: (name) => dispatch(updateName(name))
}
}
export default connect(mapStateToProps,mapDispatchToProps)(SettingsScreen);
// export default SettingsScreen;
userReducer.js
初期値の設定と、変更するための機能を実装。
// export const userReducer = (state = {}) => state;
const initialState = {
name: 'tanaka',
age: 44
}
const userReducer = (state = initialState, action) => {
// console.log(action);
switch(action.type){
case 'UPDATE_NAME':
const updateState = Object.assign({}, state);
updateState.name = action.name
return updateState;
default:
return state;
}
}
export default userReducer;
stackReducer.js
まんま返してるだけ。必要に応じて実装。
export const stackReducer = (state = {}) => state;
tabReducer.js
まんま返してるだけ。必要に応じて実装。
export const stackReducer = (state = {}) => state;
userAction.js
名前更新用のActionを実装。
export const updateName = name => {
return {
type: 'UPDATE_NAME',
name: name
}
}
まあ、とりあえず動いてます。