写作时间:2020/4/10-2020/4/15
React-Native版本:0.62.2
React-Navigation版本:5.X
Redux版本:4.0.5
开发平台:Windows
目标平台:Android
注:该项目不涉及原生内容,所以理论上在macOS上应该同样可以运行
本文将Redux和RN项目相结合,编写了一个简单的RN工程,工程界面如下(三个界面)
上面的图是首页,点击按钮可进入次级页面
上面的图是次级页面,展示了一个用户列表,该列表由Redux维护
上面的图是第三个界面(用户名编辑页面),当点击用户列表中的按钮时,进入该页面,可以修改对应用户名,修改完成返回上个页面后,可以发现列表中的第三个用户的名字发生了变化,如下图
下面给出实现的过程和代码
1 初始化RN项目,react-native init demo,并安装如下内容
// redux相关
npm install --save redux
npm install --save react-redux
npm install --save redux-logger
// react-navigation(5.x)
npm install @react-navigation/native
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
npm install @react-navigation/stack
npm install @react-navigation/bottom-tabs
2 现在先将整个项目的工程结构展示如下
components文件夹内放的就是三个界面所对应的js文件,另外action、reducers和store这三块属于Redux的内容。你可以依照项目结构创建各个文件,之后按照如下内容添加相应的代码
3 下面是各个文件所对应的代码
// actions.js
import {CHANGE_NAME} from './actionsTypes';
const changeName = (id, name) => ({type: CHANGE_NAME, id: id, name: name});
export {changeName};
// actionsTypes.js
export const CHANGE_NAME = 'CHANGE_NAME';
// DetailsScreen.js
import React from 'react';
import {View, Text, Button, FlatList} from 'react-native';
import {connect} from 'react-redux';
class DetailsScreen extends React.Component {
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'gray'}}>
<FlatList
keyExtractor={(item, index) => index.toString()}
data={this.props.user}
renderItem={({item}) => (
<View>
<Text>{item.id}</Text>
<Text>{item.name}</Text>
<Text>{item.sex}</Text>
<Text>{item.age}</Text>
<Button
title="修改姓名"
onPress={() =>
this.props.navigation.navigate('Edit', {
post: item.id,
})
}
/>
</View>
)}
/>
</View>
);
}
}
const mapStateToProps = (state) => ({
user: state.user,
});
export default connect(mapStateToProps)(DetailsScreen);
// EditScreen.js
import React from 'react';
import {View, Button, TextInput} from 'react-native';
import {connect} from 'react-redux';
import {changeName} from '../action/actions';
class EditScreen extends React.Component {
constructor() {
super();
this.state = {postText: ''};
}
render() {
return (
<View style={{flex: 1, backgroundColor: 'gray'}}>
<TextInput
multiline
placeholder="请输入新用户名"
value={this.state.postText}
onChangeText={(text) => this.setState({postText: text})}
/>
<Button
title="提交修改"
onPress={() => this.props.dispatch(changeName(this.props.route.params.post, this.state.postText))}
/>
</View>
);
}
}
export default connect()(EditScreen);
// HomeScreen.js
import React from 'react';
import {View, Text, Button} from 'react-native';
export default class HomeScreen extends React.Component {
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'gray'}}>
<Text>Home Screen</Text>
<Button title="进入详情页" onPress={() => this.props.navigation.navigate('Details')} />
</View>
);
}
}
// reducers.js
import {combineReducers} from 'redux';
import {CHANGE_NAME} from '../action/actionsTypes';
// 原始默认state
const defaultState = {
userlist: [
{
id: '001',
name: '路人甲',
sex: '女',
age: 27,
},
{
id: '002',
name: '路人乙',
sex: '女',
age: 31,
},
{
id: '003',
name: '路人丙',
sex: '男',
age: 45,
},
],
};
function user(state = defaultState.userlist, action) {
switch (action.type) {
case CHANGE_NAME:
return state.map((item) => (item.id === action.id ? {...item, name: action.name} : item));
default:
return state;
}
}
export default combineReducers({
user,
});
// store.js
import {createStore} from 'redux';
import {applyMiddleware, compose} from 'redux';
import createLogger from 'redux-logger';
import rootReducer from '../reducers/reducers';
const configureStore = (preloadedState) => {
return createStore(rootReducer, preloadedState, compose(applyMiddleware(createLogger)));
};
const store = configureStore();
export default store;
// App.js
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import HomeScreen from './components/HomeScreen';
import DetailsScreen from './components/DetailsScreen';
import EditScreen from './components/EditScreen';
import {Provider} from 'react-redux';
import store from './store/store';
const Stack = createStackNavigator();
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
<Stack.Screen name="Edit" component={EditScreen} />
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}
}
4 运行项目react-native run-android,成功!