如何在react-redux中添加到状态数组

时间:2018-04-21 21:51:24

标签: javascript reactjs redux react-redux

有点卡在这个小花絮上。我对redux很陌生,所以我只想弄明白。我试图根据球员的位置分离我的球员阵列。这一切都有效,只是状态只是不断变换到该位置的最新玩家,而不是添加到该位置的玩家阵列。以下是我的行动和减速器:

//action.js    
export const FETCH_PLAYERS_SUCCESS = 'FETCH_PLAYERS_SUCCESS';
    export const fetchPlayersSuccess = players => ({
        type: FETCH_PLAYERS_SUCCESS,
        players
    });

export const SET_WR = 'SET_WR';
export const setWR = wr => ({
    type: SET_WR,
    wr
});

export const SET_QB = 'SET_QB';
export const setQB = qb => ({
    type: SET_QB,
    qb
});

export const SET_RB = 'SET_RB';
export const setRB = rb => ({
    type: SET_RB,
    rb
});

export const SET_TE = 'SET_TE';
export const setTE = te => ({
    type: SET_TE,
    te
});

export const fetchPlayers = () => {
  return dispatch => {
    const proxyurl = "https://cors-anywhere.herokuapp.com/";
    const url = "http://api.fantasy.nfl.com/v1/players/stats?statType=seasonStats&season=2017&week=1&format=json"; // site that doesn’t send Access-Control-*
    fetch(proxyurl + url)
    .then(res => res.json())
    .catch(error => {
        console.error('Error:', error)
        dispatch(fetchPlayersError(error))
    })
    .then(response => {
        let thisPlayer = response.players
        for(let i=0; i<thisPlayer.length; i++){
            if(thisPlayer[i].position == 'WR'){
                dispatch(setWR(thisPlayer[i]))
            }
            if(thisPlayer[i].position == 'QB'){
                dispatch(setQB(thisPlayer[i]))
            }
            if(thisPlayer[i].position == 'RB'){
                dispatch(setRB(thisPlayer[i]))
            }
            if(thisPlayer[i].position == 'TE'){
                dispatch(setTE(thisPlayer[i]))
            }
        }
        dispatch(fetchPlayersSuccess(response))
    });
}}

我的减速机:

//reducer.js

const initialState = {
    players: [],
    loading: false,
    error: null,
    wr: [],
    qb: [],
    rb: [],
    te: []
};

export default (state = initialState, action) => {
    if (action.type === FETCH_PLAYERS_REQUEST) {
        return Object.assign({}, state, {
            loading: true,
            error: null
        });
    }
if (action.type === FETCH_PLAYERS_SUCCESS) {
    //console.log(state, action);
    return Object.assign({}, state, {
        players: action.players,
        loading: false
    });
}

if (action.type === SET_QB) {
    //console.log(state, action);
    return Object.assign({}, state, {
        qb: action.qb,
        loading: false
    });
}

if (action.type === SET_RB) {
    //console.log(state, action);
    return Object.assign({}, state, {
        rb: action.rb,
        loading: false
    });
}

if (action.type === SET_WR) {
    //console.log(state, action);
    return Object.assign({}, state, {
        wr: action.wr,
        loading: false
    });
}

if (action.type === SET_TE) {
    //console.log(state, action);
    return Object.assign({}, state, {
        te: action.te,
        loading: false
    });
}
if (action.type === FETCH_PLAYERS_ERROR) {
    return Object.assign({}, state, {
        loading: false,
        error: action.error
    });
}
return state;
};

感谢您提前提供任何帮助。

1 个答案:

答案 0 :(得分:2)

我认为你正在覆盖状态对象。 我认为你的代码不会添加到数组中,只是覆盖它。

另外,我会将响应中的数组传递给一个调度函数,而不是在调用dispatch之前循环调用serval调度函数或格式化对象。我认为调试和维护会更容易。您只需要拨打一次电话,除非您有令人信服的理由多次拨打电话。

为reducer使用switch语句并仅在需要时更新每个数组,否则只保持数组不在当前状态。 我看到你正在使用Object.assign。相反,请尝试根据需要单独更新数组,并为每个操作返回一个新对象。

我不知道您的所有要求,但这可能会有所帮助:

export const loadPlayers = formattedRespObj => ({
    type: 'FETCH_PLAYERS_SUCCESS',
    players: formattedRespObj.players,
    wr: formattedRespObj.wr,
    qb: formattedRespObj.qb,
    rb: formattedRespObj.rb,
    te: formattedRespObj.te
});

function formatRespObj(playersResp) {
    let formattedRespObj = {players: [], wr: [], qb: [], rb: [], te: []};

    // Note, this can probably be prettier
    for (let i = 0; i < playersResp.length; i++) {
        switch (playersResp[i].position) {
            case 'WR':
                formattedRespObj.wr.push(playersResp[i]);
                break;
            case 'QB':
                formattedRespObj.qb.push(playersResp[i]);
                break;
            case 'RB':
                formattedRespObj.rb.push(playersResp[i]);
                break;
            case 'TE':
                formattedRespObj.te.push(playersResp[i]);
                break;
            default:
                console.error("Unknown player position");
                break;
        }
    }

    formattedRespObj.players = [...formattedRespObj.wr, ...formattedRespObj.qb, ...formattedRespObj.rb, ...formattedRespObj.te];

    return formattedRespObj;
}

const initialState = {
    players: [],
    loading: false,
    error: null,
    wr: [],
    qb: [],
    rb: [],
    te: []
};

export default function reducer(playersState = initialState, action) {
    switch (action.type) {
        case 'LOAD_PLAYERS':
            return {
                players: [...playersState.wr, playersState.wr],
                loading: true,
                error: null,
                wr: [...playersState.wr, action.wr],
                qb: [...playersState.qb, action.qb],
                rb: [...playersState.rb, action.rb],
                te: [...playersState.te, action.te],
            };
        case 'FETCH_PLAYERS_ERROR':
            return {
                loading: false,
                error: action.error,
                wr: playersState.wr,
                qb: playersState.qb,
                rb: playersState.rb,
                te: playersState.te
            };
        default:
            return {
                loading: false,
                error: null,
                wr: playersState.wr,
                qb: playersState.qb,
                rb: playersState.rb,
                te: playersState.te
            }
    }
}

export const fetchPlayers = () => {
    return dispatch => {
        const proxyurl = "https://cors-anywhere.herokuapp.com/";
        const url = "http://api.fantasy.nfl.com/v1/players/stats?statType=seasonStats&season=2017&week=1&format=json"; // site that doesn’t send Access-Control-*
        fetch(proxyurl + url)
            .then(res => res.json())
            .catch(error => {
                console.error('Error:', error);
                dispatch(fetchPlayersError(error));
            })
            .then(response => {
                let formattedRespObj = formatRespObj(response);
                dispatch(loadPlayers(formattedRespObj));

                dispatch(fetchPlayersSuccess(response))
            });
    }
};