簡體   English   中英

數組未定義-React Redux

[英]Array gets undefined - React Redux

我是React和Redux的新手。 試圖理解基礎知識並做一些簡單的例子,但是我在這個問題上停留了超過一天,我找不到解決方法。 我想我的錯誤是愚蠢的錯誤。

問題是我無法打印用戶數組。 調試時,變量users會加載所有更正的ID和用戶,但是在執行<li key={id}>{name}</li>三次之后,它返回到forEach並給了我這個例外: 未被捕獲TypeError:無法讀取未定義的屬性'forEach' ,其中用戶是未定義的。 而且我還得到對應於PropTypes的錯誤: 提供給HomePage的類型為array的無效prop用戶,預期對象

這是代碼:

存儲/配置Store.js

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers/index';

const initialState = {};

const middleware = [thunk];

const store = createStore(rootReducer, initialState, compose(
    applyMiddleware(...middleware),
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
));

export default store;

reducers / index.js

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

export default combineReducers({
    user: userReducer
});

reducers / userReducer.js

import { GET_USERS, ADD_USER, DELETE_USER } from '../actions/types';

const initialState = {
    users: [
        { id: 1, name: 'brunao'},
        { id: 2, name: 'flavio'},
        { id: 3, name: 'dudu'}
    ]
};

export default function(state = initialState, action) { 
    switch (action.type) {
        case GET_USERS:
            return [
                ...state
            ];
        default:
            return state;
    }
}

動作/用戶Action.js

import { GET_USERS, ADD_USER, DELETE_USER } from './types';

export const getUsers = () => {
    return {
        type: GET_USERS
    };
};

組件/HomePage.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getUsers } from '../actions/usersActions';
import PropTypes from 'prop-types';

class HomePage extends Component {

    componentDidMount() {
        this.props.getUsers();
    }

    render() {
        const { users } = this.props.user;
        return(
            <div>
                <h3>Users</h3>
                <ul>
                    {users.forEach(({id, name}) => (
                        <li key={id}>{name}</li>
                    ))}
                </ul>
            </div>
        );
    }

}

HomePage.propTypes = {
    getUsers: PropTypes.func.isRequired,
    user: PropTypes.object.isRequired
}

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

export default connect(mapStateToProps, { getUsers })(HomePage);

您在減速器中返回了錯誤的狀態。 您的相關代碼:

export default function(state = initialState, action) { 
    switch (action.type) {
        case GET_USERS:
            return [
                ...state
            ];
        default:
            return state;
    }
}

在這里,狀態是一個對象,但是您要通過傳播將其以數組形式返回。 因此,您的狀態被破壞了。

像這樣嘗試:

case GET_USERS:
    return state;

正如@Idan Dagan在他的回答中指出的那樣,實際上,我們不會在化簡器中改變狀態。 我剛剛提出了這個建議,因為您只是在玩耍學習Redux,我們將在這里返回原始狀態,僅此而已。 但是,這是一種返回狀態的合適且更好的方法:

case GET_USERS:
    return { ...state };

這是一個工作代碼: https : //codesandbox.io/s/k5ymxwknpv

我也按照@Idan Dagan的建議再次更改了forEachmap 我還沒意識到。 forEach在這里不是合適的方法,因為它實際上不返回任何內容。 您想在React中映射數組並渲染它們。

另外,您的州名令人困惑:) user.users ,您可能認為更好的一個。

評論后編輯

您的GET_USERS動作實際上已被擊中,但您在代碼中檢查的是錯誤的。 您正在執行:

export default function(state = initialState, action) {
  switch (action.type) {
    case GET_USERS:
      return Object.assign({}, state);
    default:
      return {
        users: [
          { id: 1, name: "TEST" },
          { id: 2, name: "TEST1" },
          { id: 3, name: "TEST2" }
        ]
      };
  }
}

這里會發生什么? Redux的第一個動作是INIT 這是您狀態的初始化。 現在,由於沒有任何動作,減速器將達到默認情況並返回TEST。 現在,您的狀態成為該TEST數據。 然后,您的GET_USERS被擊中,並且您返回一個新對象,該對象合並了處於測試狀態的狀態。 步驟如下:

First, state is the `initialState` -> `INIT` runs and hits the default case
State is now TEST one -> GET_USERS hit and returns the `state` which is TEST one
You see the TEST one.

您如何測試自己的行為? 只需將console.log放入您的reducer中:

export default function(state = initialState, action) {
  console.log("state",state);
  console.log("action",action);
  .....

並看到GET_USERS實際上被擊中了。 另一個選擇是代替返回帶有state的合並對象,嘗試將其與initialState合並,或者使用spread運算符通過使用initialState返回一個新對象:

return return Object.assign({}, initialState);

要么

return {...initialState}

最后一個選項使您更加了解我的第一個解釋的工作原理。 嘗試為您的GET_USERS返回此代碼:

return {...state, users:[...state.users, {id:4, name: "foo"}]};

您將看到一個包含TEST數據的用戶列表,但最后一個將是您的foo 這說明了如果在默認情況下返回除state任何內容,將如何initialState

最后的建議是,您可以使用Redux Dev Tools調試您的Redux開發。 它是一個很棒的工具,除了調試以外,還可以做更多的事情。 您可以輕松跟蹤Redux的所有操作。

我不確定您要如何處理新狀態。

但是您需要做一些更改:

  1. 使用map而不是forEach (因為您想返回一個新數組)。
  2. 在減速器上,您可以返回如下狀態:

 export default function(state = initialState, action) { switch (action.type) { case GET_USERS: return Object.assign({}, state); default: return state; } } 

redux文檔中所述

我們不改變國家 我們使用Object.assign()創建一個副本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM