问题
重新启动应用程序时,存储没有保留或以某种方式被重置
预期行为
该应用程序基本上只有一个登录表单,其中触发了一些还原操作。例如,用户名和密码都会保存到商店中。
在使用Reactotron进行检查之后,商店实际上按照预期的方式进行了开发,用户名和密码以及其他字段均已更新。
技术栈
使用Redux响应本机应用(不是Expo)
package.json
"dependencies": {
"react": "16.6.1",
"react-native": "0.57.7",
"react-native-gesture-handler": "^1.0.12",
"react-native-i18n": "^2.0.15",
"react-navigation": "^3.0.8",
"react-redux": "^6.0.0",
"redux": "^4.0.1",
"redux-persist": "^5.10.0"
},
申请状态
我已经创建了一个简单的ReactNative应用,其中根组件为:
App.js
import React, {Component} from 'react';
import { Provider } from 'react-redux';
import LoadingIndicator from '@components/Visual/LoadingIndicator/';
import MainNavigator from '@components/Visual/MainNavigator'
import {checkUserState} from '@actions/GlobalActions'
import {store, persistor} from '@components/Storage/StorageConfigurationBuilder'
import { PersistGate } from 'redux-persist/integration/react'
export default class App extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
store.dispatch(checkUserState())
}
render() {
return (
<Provider store={store}>
<PersistGate loading={<LoadingIndicator />} persistor={persistor}>
<MainNavigator initialRoute={this.props.initialRoute} />
</PersistGate>
</Provider>
);
}
}
导入中的 @components
和@actions
由babel插件“ module-resolver”解决。
.babelrc
...
["module-resolver", {
"root": ["."],
"alias": {
"^@constants/(.+)": "./constants/\\1",
"@i18n": "./i18n/index.js",
"^@components/(.+)": "./components/\\1",
"^@screens/(.+)": "./screens/\\1",
"^@reducers/(.+)": "./reducers/\\1",
"^@actions/(.+)": "./actions/\\1",
}
}]
...
在同时提供商店和持久性的路线应用程序中导入的StorageConfigurationBuilder很简单:
StorageConfigurationBuilder.js
import { createStore } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage/index.native'
import AllReducers from '@reducers/AllReducers'
//import Reactotron from '../../ReactronConfig'
const persistConfig = {
key: 'root',
storage
}
const persistedReducer = persistReducer(persistConfig, AllReducers)
export const store = createStore(persistedReducer)
export const persistor = persistStore(store)
最后,将要呈现的视图组件分为两部分
index.js
import React, {Component} from 'react'
import { connect } from 'react-redux';
import LoginView from './LoginView';
import {loginFetch, loginFetchError, loginFetchSuccess} from '@actions/UserActions'
import ApiConfiguration, { getApiBaseUri } from '@constants/ApiConfiguration'
class LoginController extends Component {
constructor(props) {
super(props)
}
doLogin() {
this.props.dispatch(loginFetch());
fetch(getApiBaseUri() + ApiConfiguration.endpoints.authentication.path, {
...ApiConfiguration.headers,
method: ApiConfiguration.endpoints.authentication.method,
body: JSON.stringify({
email: this.props.email,
password: this.props.password
})
}).then((response) => {
return response.json()
}).then((response) => {
this.props.dispatch(loginFetchSuccess(response))
}).catch((e) => {
this.props.dispatch(loginFetchError(e))
})
}
render() {
return <LoginView {...this.props} login={this.doLogin.bind(this)} />;
}
}
const mapStateToProps = (state) => {
const { user } = state
return { user }
};
export default connect(mapStateToProps)(LoginController);
视图<LoginView />
本身没有什么特别之处
LoginView.js
import React from 'react';
import {StyleSheet, SafeAreaView, View, TextInput, Text, TouchableOpacity} from 'react-native';
import {changeEmail, changePassword} from '@actions/UserActions'
import I18n from '@i18n';
import Colors from '@constants/Colors';
export default props => {
return (<SafeAreaView style={styles.container}>
<View style={styles.loginForm}>
<View style={styles.fieldContainer}>
<Text style={styles.fieldLabel}>{I18n.t('login.email_label')}</Text>
<TextInput
value={props.user.email}
onChangeText={value => props.dispatch(changeEmail(value))}
placeholder={I18n.t('login.email_placeholder')}
style={styles.field}
textContentType={"username"}
returnKeyType={"next"}
underlineColorAndroid={"transparent"}></TextInput>
</View>
<View style={styles.fieldContainer}>
<Text style={styles.fieldLabel}>{I18n.t('login.password_label')}</Text>
<TextInput
value={props.user.password}
onChangeText={value => props.dispatch(changePassword(value))}
style={styles.field}
placeholder={I18n.t('login.password_placeholder')}
textContentType={"password"}
underlineColorAndroid={"transparent"}
secureTextEntry={true}></TextInput>
</View>
<View style={styles.panelFooter}>
<TouchableOpacity onPress={() => props.login()}>
<Text>
{I18n.t('login.login_button')}
</Text>
</TouchableOpacity>
</View>
</View>
</SafeAreaView>);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.backgroundColor,
justifyContent: 'center'
},
loginForm: {
marginLeft: 20,
marginRight: 20,
justifyContent: 'space-around',
borderWidth: 1,
borderColor: Colors.borderColor,
borderRadius: 5
},
panelFooter: {
flexDirection: 'row',
justifyContent: 'flex-end',
backgroundColor: '#e5e5e5',
height: 44,
paddingRight: 20,
paddingTop: 13,
marginTop: 35
},
fieldContainer: {
height: 50,
flexDirection: 'column',
marginLeft: 20,
marginRight: 20,
marginTop: 25
},
fieldLabel: {
fontSize: 13,
fontWeight: "600",
marginBottom: 4,
marginLeft: 10
},
field: {
height: 44,
borderWidth: 1,
borderColor: Colors.borderColor,
borderRadius: 22,
fontSize: 18,
paddingLeft: 22,
paddingRight: 10
}
})
答案 0 :(得分:0)
因此,我添加了一个简单的reducer / action并将其附加到我的应用程序中,即与上述相同的应用程序。我从先前创建的另一个standalone project处获得了此代码,效果很好。
在这部分中,FriendReducer继续正常工作,而上述我的减速器仍无法正常工作。
最后,我在reducer中添加了以下情况以恢复我的应用程序状态。由于某种原因,它不是自己做的。
case 'persist/REHYDRATE':
//rehydrating userStore to app
newState = { ...action.payload.userStore }
return newState