如何在本机反应中将状态传递给容器

时间:2018-09-08 10:26:01

标签: reactjs react-native redux react-redux

我正在学习本机响应,并且正在构建应用程序。对于某些概念,我无法理解魔术发生的位置。我正在使用redux存储管理数据。

我有一个无状态登录组件。

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.log("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存储中用户属性的状态。我无法了解如何将状态或操作传递给登录组件。任何解释将不胜感激。

2 个答案:

答案 0 :(得分:3)

在react-native中管理redux存储基本上与在react中相同。

据我了解,您正在尝试在每个onChangeText事件上将用户详细信息存储在redux存储中,并在Login组件中反映更新后的状态。

首先,您应该使用单独的动作减少器对在redux中设置用户详细信息。另外,您很可能希望在表单提交时调用一些API并将响应存储在redux中。为此,您可能需要另一对操作和reducer。我留给你

这是您如何在Redux中管理用户详细信息...

您的无状态登录组件。

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

  render() {
    const { user, onSubmitForm } = this.props
    console.log('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)

...

您的Reducer用于设置用户详细信息

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
  }
}

...

希望有帮助。

答案 1 :(得分:1)

希望有帮助:

登录:

您绝不能更新该组件内的组件props。

React documentation

  

道具是只读的

如果您希望将状态(真相)存储在登录组件中,则将其存储为适当的状态,并在提交时发送此本地状态:

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 documentation

  

如果传递了一个对象,则假定其中的每个函数都是Redux操作创建者。一个具有相同功能名称的对象,但是每个动作创建者都被包装到一个调度调用中,以便可以直接调用它们,这些对象将被合并到组件的props中。

所以您编写的代码:

const mapDispatchToProps = {
  ...fetchUserDetails,
}

等效于此代码

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

神奇的地方是dispatch函数,调度的每个动作都传递给减速器,您可以在其中根据动作创建新状态。