【问题标题】:Redux state not updating after action dispatched动作分派后 Redux 状态未更新
【发布时间】:2020-11-09 15:31:59
【问题描述】:

我有一个表格供用户输入他们的详细信息并按提交。这应该通过.concat() 一个类来调度一个动作并更新状态。不幸的是,状态没有更新,我不知道为什么。如果我从代码中取出useCallBack()useEffect(),模拟器就会死机,我怀疑是无限循环。

Redux 减速器

// Initialised class
import newAccount from '../../models/newAccount'

import { CREATE_ACCOUNT } from '../actions/meals'

const initialState = {
    account: [],
}
const addPerson = (state=initialState, action) =>{
    switch(action.type){
        case CREATE_ACCOUNT:
            const newAccount = new newAccount(
                Date.now().toString(),
                action.accountData.name, 
                action.accountData.image,
                action.accountData.email,
                action.accountData.password
            )
            return { ...state, account: state.account.concat(newAccount) }
    default: 
        return state
    }
}
export default addPerson

Redux 操作

export const CREATE_ACCOUNT = 'CREATE_ACCOUNT'
export const newAccount = (Id,name,image, email, password) => {
    return {type: CREATE_ACCOUNT, accountData:{
            Id: Date.now().toString(),
            name: name,
            image: image,
            email: email,
            password: password
        }
    }
}

班级

class newAccount {
    constructor( 
        id,
        name,
        image,
        email,
        password
    ){
        this.id = id;
        this.name = name;
        this.image = image;
        this.email = email;
        this.password = password;
    }
}
export default newAccount

组件

import React, { useState, useCallback, useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import {newAccount} from '../Store/actions/accounts'
import ImagePicker from '../Components/ImagePicker'

const AddScreen = (props) => {

    const dispatch = useDispatch()
    const [name, setName] = useState('')
    const [selectedImage, setSelectedImage] = useState('')
    const email = useSelector(state => state.account.email)
    const password = useSelector(state => state.account.password)

    const handleSubmit = useCallback(() => {
        dispatch(newAccount(Date.now(),name,selectedImage,email,password))
    },[dispatch, name, selectedImage, email, password])

    useEffect(() => { handleSubmit
        props.navigation.setParams({handleSubmit: handleSubmit})
    },[handleSubmit])
    
    return (
        <View style={styles.container}>
            <View style={styles.card}>
                <ImagePicker onImageSelected={selectedImage} />
                <AddForm email={email} password={password}/>
                <TextInput
                    onChangeText={name => setName(name)}
                    value={name}
                />
            </View>
        </View>
    )
}

export default AddScreen

AddScreen.navigationOptions = (navigationData) => {
    const submit = navigationData.navigation.getParam('handleSubmit')
    return {
        headerTitle: 'Create Account',
        headerRight: () => (
            <TouchableOpacity  onPress={submit}>
                <Text style={styles.createOrange}>Create</Text> 
            </TouchableOpacity>
        )
    }
}

真不知道为什么不更新了。

【问题讨论】:

  • 你试过了吗:return { ...state, account: [...state.account, newAccount] }

标签: javascript react-native redux react-redux


【解决方案1】:

首先,你不应该在 redux 存储中存储类,存储应该只存在于普通对象中。但如果你真的想存储类:

真正的问题接缝是return { ...state, account: state.account.concat(newAccount) }。在这里,您将现有数组与新类连接起来,但这不起作用。

如果你这样做,你的商店看起来像这样:

{
  account: [{
    email: "..."
    id: "..."
    image: "..."
    name: "..."
    password: "...
  }],
}

所以您的选择器 (state.account.email) 将返回未定义。你可以使用 (state.account[0].email)

或者你可以通过解决真正的问题来解决它:

return { ...state, account: newAccount }

你的 initialState 也不应该是一个数组,因为它永远不会是一个数组,它将是一个 Account 类(这就是为什么你不会因为你正在做的事情而出错)。将其设置为null

const initialState = {
  account: null,
}

【讨论】:

    【解决方案2】:

    我真的不知道为什么这不起作用。只是想给你一个建议,让它更简单、更清晰(从我的角度来看):

    您可以删除像useEffect 这样的副作用。要实现这一点,只需将本地状态移动到 redux 状态,然后您就可以从 navigationOptions 组件中调度操作。它可能看起来像:

    const AddScreen = () => {
      const name = useSelector(...);
      ...
      const password = useSelector(...);
    
      // trigger action on something changes, for instance like that:
      const onChange = (key, value) = dispatch(newAccountChange({[key]: value}))
    
      // return tree of components
    }
    
    export const submitNewAccount = () => {
      return (dispatch, getState) => {
        const { id, name, ... } = getState().account;
        dispatch(newAccount(id, name, ...));
      };
    }
    
    AddScreen.navigationOptions = (navigationData) => {
      const dispatch = useDispatch();
      const submit = dispatch(submitNewAccount());
      ...
    }
    

    我在这个例子中使用了redux-thunk

    我相信,这种方法将为您提供更灵活的方式来调试和扩展业务逻辑。

    【讨论】:

    • 'const dispatch = useDispatch()' 给出了无效的钩子调用错误,因为它不在功能组件中,而是在 navigationOptions 中。我将如何使用您的示例解决此问题
    • 哦,我明白了,navigationOptions 只是一个函数,而不是一个组件。好的,那么你可以用钩子定义HeaderRight组件并使用就像:navigationOptions = ()=&gt; ({headerRight: ()=&gt; &lt;HeaderRight /&gt;})HeaderRightconst HeaderRight = ()=&gt; { const dispatch = useDispatch();... }
    猜你喜欢
    • 2020-04-22
    • 2018-09-03
    • 2021-12-10
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 2019-05-30
    相关资源
    最近更新 更多