如何将状态传递给反应原生的容器

问题描述 投票:1回答:2

我正在学习反应本机,我正在构建一个应用程序。对于某些概念,我无法理解魔法在哪里发生。我正在使用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.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存储中用户属性的状态。我无法了解状态或操作将如何传递给Login组件。任何解释将不胜感激。

reactjs react-native redux react-redux
2个回答
3
投票

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

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

首先,您应该使用单独的action reducer对来设置redux中的用户详细信息。此外,您最有可能想要在表单提交上调用一些API并将响应存储在redux中,为此您可能需要另一对action和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
投票

希望有所帮助:

登录:

您必须永远不要更新所述组件内的组件道具。

来自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函数是魔术发生的地方,每个被调度的动作都会传递给你的reducer,你可以根据动作创建一个新的状态。

© www.soinside.com 2019 - 2024. All rights reserved.