Приложение переходит на начальный экран после отправки формы и изменения состояния - PullRequest
0 голосов
/ 31 августа 2018

Приложение сбрасывается на начальный экран после отправки формы (приставка или Formik). Экран входа в систему является вторым экраном в начальном маршруте (первым является экран «Пуск»). После подтверждения отправки вызова и возврата в новое состояние -> {... состояние, ... {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,
})

1 Ответ

0 голосов
/ 13 сентября 2018

Я исправил эту проблему. Проблема была в основном контейнере, где я монтировал 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)
...