Как передать состояние контейнеру в React Native

Я изучаю React Native и создаю приложение. Для некоторых концепций я не могу понять, где происходит волшебство. Я использую redux store для управления данными.

У меня есть компонент входа в систему без сохранения состояния.

export class Login extends Component {
   onChangeText = (key, value) => {
     this.props.user[key] = value
  }

  render() {
    const { user, fetchUserDetails } = this.props
    return (
      <View style = {styles.container}>
        <Text style = {styles.heading}>Login</Text>
        <TextInput
          placeholder='Email'
          onChangeText = {val => this.onChangeText('email', val)}
          value = {user.email}
        />
        <TextInput
          placeholder='Password'
          onChangeText = {val => this.onChangeText('password', val)}
          value = {user.password}
        />
        <TouchableOpacity onPress = {this.fetchUserDetails(user)}>
          <View style = {styles.button}>
            <Text style = {styles.buttonText}>Login</Text>
          </View>
        </TouchableOpacity>
      </View>
    )
  }
}

Это мой контейнер для входа

class LoginContainer extends Component {

  render () {
    return (
      <Login/>
    )
  }
}

const mapStateToProps = (state) => ({
  user: state.loginReducer.user,
})

const mapDispatchToProps = {
  ...fetchUserDetails,
}

export default connect(mapStateToProps, mapDispatchToProps)(Login)

мой редуктор выглядит так:

const initialState = {
  user: {
    email: '',
    password: '',
  }
}

const loginReducer = (state = initialState, action) => {
  switch(action.type) {
    case GET_USER:
      return Object.assign({}, state, {
        user: action.user
      })
    default:
      return state
  }
  return state
}

export default loginReducer

Мои действия выглядят примерно так:

export const GET_USER = 'GET_USER'
export function fetchUserDetails (user) {
  console.info("executing fetch user action")
  if (user === '')
  {
    alert('please complete form')
  }
  return {
    type: GET_USER,
    user
  }
}

Мой корневой редуктор:

import { combineReducers } from 'redux';
import loginReducer from './loginReducer'
const rootReducer = combineReducers({
  loginReducer
})

export default rootReducer

Мой магазин настроек:

import { createStore } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import rootReducer from './reducers'

const persistConfig = {
  key: 'mykey',
  storage,
}

const persistedReducer = persistReducer(persistConfig, rootReducer)
const store = createStore(persistedReducer)
const persistedStore = persistStore(store)

export default store

Мне нужен компонент без сохранения состояния, который напрямую обновляет состояние пользовательских атрибутов в хранилище redux. Я не могу следить за тем, как состояние или действия будут переданы компоненту входа в систему. Любое объяснение будет оценено.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
284
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Надеюсь, это поможет:

Авторизоваться:

НИКОГДА не обновляйте свойства компонента внутри указанного компонента.

Из Документация React:

Props are Read-Only

Если вы хотите, чтобы ваше состояние (истина) сохранялось в компоненте входа в систему, сохраните его как правильное состояние и отправьте это локальное состояние при отправке:

onChangeText = (key, value) => {
   this.setState((state) => ({ ...state, [key] => value}))
}

Однако, если вы хотите сохранить свое состояние в redux, вам нужно будет создать действие, которое может быть запущено для обновления состояния redux. Это действие необходимо передать в свойства компонента и называть его следующим образом: onChangeText = {val => this.props.onChangeText('email', val)}.

Кроме того, вы вызываете функцию fetchUserDetails при рендеринге, где вы должны передавать обратный вызов. this.fetchUserDetails не существует, this.props.fetchUserDetails существует. Код входа становится

<TouchableOpacity onPress = {() => fetchUserDetails(user)}>

Контейнер входа в систему:

mapDispatchToProps должен быть функцией, которая принимает dispatch в качестве первого параметра ИЛИ объектом, где каждая функция является создателем действия. Из Документация Redux:

If an object is passed, each function inside it is assumed to be a Redux action creator. An object with the same function names, but with every action creator wrapped into a dispatch call so they may be invoked directly, will be merged into the component’s props.

Итак, код, который вы написали:

const mapDispatchToProps = {
  ...fetchUserDetails,
}

Эквивалентно этому коду

function mapDispatchToProps(dispatch) {
    return {
        fetchUserDetails: (user) => dispatch(fetchUserDetails(user))
    },
}

Функция dispatch - это то место, где происходит волшебство, каждое отправленное действие передается вашим редукторам, где вы можете создать новое состояние на основе действия.

Ответ принят как подходящий

Управление хранилищем redux в react-native в основном такое же, как и в react.

Насколько я понимаю, вы пытаетесь хранить данные пользователя в хранилище redux для каждого события onChangeText и отражать обновленное состояние в компоненте входа в систему.

Во-первых, вы должны использовать отдельную пару редукторов действий для настройки данных пользователя в redux. Также вы, скорее всего, захотите вызвать какой-либо API при отправке формы и сохранить ответ в redux. Для этого вам может потребоваться другая пара действий и редуктора. Я оставлю это тебе

Вот как вы можете управлять данными пользователя в сокращении ...

Ваш компонент входа в систему без сохранения состояния.

export class Login extends Component {
   onChangeText = (value, key) => {
     this.props.setUserDetails({
       ...this.props.user,
       [key]: value
     })
  }

  render() {
    const { user, onSubmitForm } = this.props
    console.info('user===>', this.props);
    return (
      <View style = {styles.container}>
        <Text style = {styles.heading}>Login</Text>
        <TextInput
          placeholder='Email'
          onChangeText = {val => this.onChangeText(val, 'email')}
          placeholderTextColor = {'rgba(0,40,70,0.5)'}
          value = {user.email}
        />
        <TextInput
          placeholder='Password'
          onChangeText = {val => this.onChangeText(val, 'password')}
          placeholderTextColor = {'rgba(0,40,70,0.5)'}
          value = {user.password}
        />
        <TouchableOpacity onPress = {() => onSubmitForm(user)}>
          <View style = {styles.button}>
            <Text style = {styles.buttonText}>Login</Text>
          </View>
        </TouchableOpacity>
      </View>
    )
  }
}

...

Ваш контейнер для входа в систему.

class LoginContainer extends Component {
  onSubmitForm = () => {
    // Checking Validations
    const { name, email } = this.props;
    if (!name || !email) {
      alert('Please fill the form')
      return;
    }

    // call some API for verification and handle the response here
  }

  render () {
    return (
      <Login
        user = {this.props.user}
        setUserDetails = {this.props.setUserDetails}
        onSubmitForm = {this.onSubmitForm}
      />
    )
  }
}

const mapStateToProps = (state) => ({
  user: state.userReducer.user,
})

const mapDispatchToProps = dispatch => ({
  setUserDetails: payload => dispatch(setUserDetails(payload)),
})

export default connect(mapStateToProps, mapDispatchToProps)(LoginContainer)

...

Ваш редуктор для настройки данных пользователя

const initialState = {
  user: {
    email: '',
    password: '',
  }
}

const userReducer = (state = initialState, action) => {
  switch(action.type) {
    case 'SET_USER_DETAILS':
      return Object.assign({}, state, {
        user: action.user
      })
    default:
      return state
  }
  return state
}

export default userReducer

...

Ваш магазин останется прежним, а rootReducer должен быть

import { combineReducers } from 'redux';
import userReducer from './reducer'

const rootReducer = combineReducers({
  userReducer
})

export default rootReducer

...

Наконец-то ваше действие

export const SET_USER_DETAILS = 'SET_USER_DETAILS'

export function setUserDetails (user) {
  return {
    type: 'SET_USER_DETAILS',
    user
  }
}

...

Надеюсь, это поможет.

Я попробовал ваше решение, но потом у меня возникла ошибка, что user.email не определен в компоненте входа в систему. Фактически ни одно из свойств не передается компоненту входа в систему.

Hassan Abbas 08.09.2018 18:48

Правильно ли вы настроили root-reducer. Я предполагаю, что вы назначили там состояние с именем userReducer для своего userReducer. Попробуйте проверить значения в Логин. Также проверьте, получаете ли вы правильные значения в действии и редукторе. Если нет, то правильно настройте root-reducer. Получите помощь от этого документы.

Arpit Kapadia 08.09.2018 19:10

Что вы имеете в виду под «состоянием с именем userReducer»? Код, который вы разместили в своем ответе, состоит из моего пользователя Reducer.

Hassan Abbas 08.09.2018 19:23

Redux предоставляет вам функцию с именем «combReducer», которая объединяет все ваши редукторы в один редуктор, который затем передается в ваше хранилище redux. он принимает состояния отображения объектов с соответствующими редукторами. Я предполагал, что вы назвали свое состояние таким же, как имя редуктора, то есть userReducer, как этот combReducers ({userReducer: userReducer}), а затем передали его в магазин.

Arpit Kapadia 08.09.2018 19:44

Да, это уже сделано, но опять же, я просто не могу получить к нему доступ. Я внесу правку, добавив свой корневой файл-редуктор и файл configureStore.

Hassan Abbas 08.09.2018 19:52

Попробуйте сейчас Я изменил несколько битов в своем ответе.

Arpit Kapadia 09.09.2018 00:04

Другие вопросы по теме