表单提交后,应用程序将重置为初始屏幕(redux-form或Formik)。登录屏幕是初始路线中的第二个屏幕(首先是“开始”屏幕)。在提交调用发送并返回新状态后 - > {... state,... {isLoading:true}}并在此步骤中我的应用程序重置。
我究竟做错了什么?如何在不重置的情况下使表单正常工作?
LoginScreen.js
import React, { Component } from 'react'
import { View, Text, Button } from 'react-native'
import { connect } from 'react-redux'
import { LoginForm } from '../../forms'
import { userLogin } from '../../store/modules/account'
import s from './styles'
class LoginScreen extends Component {
onLogin = (values, bag) => {
const { userLogin } = this.props
const { email, password } = values
userLogin({ email, password })
}
render() {
const { account, navigation } = this.props
return (
<View style={s.wrapper}>
<View style={s.mainContainer}>
<Text>This is SignIiiiiiin!</Text>
<LoginForm
handleLogin={this.onLogin}
/>
</View>
</View>
)
}
}
const mapStateToProps = ({ account }) => ({
account,
})
export default connect(mapStateToProps, {
userLogin
})(LoginScreen)
LoginForm.js
import React, { Component } from 'react'
import { View, TouchableOpacity, Button } from 'react-native'
import { Formik } from 'formik'
import { FieldInput } from '../../components'
import s from './styles'
class LoginForm extends Component {
render() {
const {
handleLogin,
} = this.props
return (
<View style={s.wrapper}>
<Formik
initialValues={{ email: '', password: '', confirmPassword: '' }}
onSubmit={handleLogin}
render={({
values,
handleSubmit,
setFieldValue,
errors,
touched,
setFieldTouched,
isValid,
isSubmitting,
}) => (
<React.Fragment>
<FieldInput
label="Email"
autoCapitalize="none"
value={values.email}
onChange={setFieldValue}
onTouch={setFieldTouched}
name="email"
error={touched.email && errors.email}
/>
<FieldInput
label="Password"
autoCapitalize="none"
secureTextEntry
value={values.password}
onChange={setFieldValue}
onTouch={setFieldTouched}
name="password"
error={touched.password && errors.password}
/>
<FieldInput
label="Confirm Password"
autoCapitalize="none"
secureTextEntry
value={values.confirmPassword}
onChange={setFieldValue}
onTouch={setFieldTouched}
name="confirmPassword"
error={touched.confirmPassword && errors.confirmPassword}
/>
<Button
backgroundColor="blue"
title="Submit"
onPress={handleSubmit}
disabled={!isValid || isSubmitting}
loading={isSubmitting}
/>
</React.Fragment>
)}
/>
</View>
)
}
}
export default LoginForm
存储/ index.js
import { applyMiddleware, compose, createStore } from 'redux'
import thunk from 'redux-thunk'
import { persistStore, persistReducer } from 'redux-persist'
import logger from 'redux-logger'
import storage from 'redux-persist/lib/storage'
import makeRootReducer from './reducers'
const persistConfig = {
key: 'root',
storage,
blacklist: ['account']
}
const persistedReducer = persistReducer(persistConfig, makeRootReducer)
const enhancer = compose(applyMiddleware(thunk, logger))
export default function configureStore() {
const store = createStore(persistedReducer, enhancer)
const persistor = persistStore(store)
return { store, persistor }
}
存储/模块/ account.js
import { AsyncStorage } from 'react-native'
import { cloneDeep, assignIn, merge } from 'lodash'
import axios from 'axios'
import moment from 'moment'
import CNST from '../constants'
import { ENV } from '../../config'
// ------------------------------------
// Actions
// ------------------------------------
export function userLogin(data = {}) {
const username = data.email
const password = data.password
return (dispatch) => {
dispatch({
type: CNST.ACCOUNT.LOGIN.LOADING
})
/*
axios.post(`${ENV.ROOT_URL}/user/login`, { username, password })
.then((response) => {
const { token } = response.data
const validFrom = moment().format()
dispatch({
type: CNST.ACCOUNT.LOGIN.SUCCESS,
response: { token, username, validFrom }
})
return response
})
.catch((error) => {
console.log('error', error.response)
dispatch({
type: CNST.ACCOUNT.LOGIN.FAILED,
response: error
})
})
*/
}
}
// ------------------------------------
// Reducers
// ------------------------------------
const initialState = {
id: '',
email: '',
username: '',
token: '',
error: {},
isLoading: false
}
export default function accountReducer(state = cloneDeep(initialState), action) {
switch (action.type) {
case CNST.ACCOUNT.LOGIN.SUCCESS: {
// console.log('action', action)
const { token, username, validFrom } = action.response
const _items = [
['token', token || ''],
['username', username || ''],
['validFrom', validFrom || ''],
]
AsyncStorage.multiSet(_items)
return { ...state, ...{ error: {}, token, username, email: username, isLoading: false } }
}
case CNST.ACCOUNT.LOGIN.FAILED:
return { ...state, ...{ error: action.response, isLoading: false } }
case CNST.ACCOUNT.LOGIN.LOADING:
return { ...state, ...{ isLoading: true } }
default:
return state
}
}
存储/常数/ account.js
export default {
LOGIN: {
LOADING: 'LOGIN',
SUCCESS: 'LOGIN_SUCCESS',
FAILED: 'LOGIN_FAILED'
}
}
存储/ reducers.js
import { combineReducers } from 'redux'
import account from './modules/account'
export default combineReducers({
account,
})
我解决了这个问题。问题是在主容器中我安装Navigator并传递状态以更改不同堆栈之间的路由。我传递了所有状态对象,当一个对象的项目被更改时,导航器重置导航状态。
. . .
return (
<View style={{ flex: 1 }}>
<Navigator
onNavigationStateChange={() => Keyboard.dismiss()}
/>
</View>
)
}
}
const mapStateToProps = ({ account }) => ({
account // <-- bad idea
token: account.token // <-- good one
})
export default connect(mapStateToProps, {
getSomeData
})(MainContainer)