Как перевести ответ XHR-запроса в состояние с помощью React-Redux - PullRequest
0 голосов
/ 01 апреля 2020

Я пытаюсь получить ответ на запрос XHR в качестве опоры в моем контейнере React. Я пытаюсь сделать GET-запрос к API и превратить ответ в объект под названием «игра», к которому я могу получить доступ в реакции. Я успешно сделал нечто подобное с GET-запросом, который вернул массив объектов под названием «игры», которые я мог отобразить в реакции; однако, когда я пытаюсь запросить объект «игра», я получаю хороший ответ от API, но при реакции отображается «игра» как неопределенная.

Я думаю, что проблема, с которой я столкнулся, может быть связана с моим файл редуктора или действия, возможно, как мне настроить исходное состояние, но я не могу понять, как заставить его работать.

Спасибо за любую помощь, которую вы можете предоставить! Я действительно ценю ваше время и терпение.

Я публикую свой код ниже.

Файл редуктора выглядит следующим образом:

import { LOAD_GAMES, SET_CURRENT_GAME } from "../actionTypes";

const game = (state = [], action) => {
    switch (action.type) {
        case LOAD_GAMES:
            return [...action.games];
        case SET_CURRENT_GAME:
            return [...action.game];
        default:
            return state;
    }
};

export default game;

Файлы действий выглядят так:

import { apiCall } from "../../services/api";
import { addError } from "./errors";
import { LOAD_GAMES, SET_CURRENT_GAME } from "../actionTypes"; 

export const loadGames = games => ({
  type: LOAD_GAMES,
  games
});

export const setCurrentGame = game => ({
    type: SET_CURRENT_GAME,
    game
});

export const fetchGames = () => {
  return dispatch => {
    return apiCall("GET", "api/games/")
      .then(res => {
        dispatch(loadGames(res));
      })
      .catch(err => {
        dispatch(addError(err.message));
      });
  };
};

//WRITE A FUNCTION TO SET_CURRENT_GAME TO BE THE ID OF THE GAME THAT IS CLICKED ON.
export const getGameDetails = game_id => {
    return dispatch => {
        return apiCall("GET", `/api/games/${game_id}`)
            .then(res => {
                dispatch(setCurrentGame(res));
        })
        .catch(err => {
            dispatch(addError(err.message));
        });
    };
};

export const postNewGame = title => (dispatch, getState) => {
  return apiCall("post", "/api/games", { title })
    .then(res => {})
    .catch(err => addError(err.message));
};

И контейнер React выглядит следующим образом:

import React, { Component } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { getGameDetails } from "../store/actions/games";

class GameDetails extends Component {

componentDidMount() {
    const game_id= this.props.match.params.game_id;
    this.props.getGameDetails(game_id);
}
render() {
    const { game } = this.props;

    return (
        <div className="home-hero">
            <div className="offset-1 col-sm-10">
                    <h4>You are viewing the Game Page for {game.title}</h4>
            </div>
        </div>
    );
}
}

function mapStateToProps(state) {
return {
    game: state.game
    };
}

export default connect(mapStateToProps, { getGameDetails })(
    GameDetails
);

EDIT - Контейнер GameList, который работает, отображая карту массива ответов игр, выглядит следующим образом:

import React, { Component } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { fetchGames } from "../store/actions/games";

class GameList extends Component {
    componentDidMount() {
        this.props.fetchGames();
    }
    render() {
        const { games } = this.props;
        let gameList = games.map(g => ( 
            <li className="list-group-item" key= {g._id}>
                <Link to={`/games/${g._id}`}>
                    {g.title}
                </Link>
            </li>
        ));
        return (
            <div className="row col-sm-8">
                <div className="offset-1 col-sm-10">
                    <ul className="list-group" id="games">
                        {gameList}
                    </ul>
                </div>
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        games: state.games
    };
}

export default connect(mapStateToProps, { fetchGames })(
    GameList
);

Для пояснения, часть «LOAD_GAMES» редуктора и действий работает хорошо; однако «SET_CURRENT_GAME» не работает.

1 Ответ

0 голосов
/ 01 апреля 2020

Я думаю, что вы используете редуктор неправильно

Состояние редуктора должно быть объектом, а не массивом IMO, например так:

import { LOAD_GAMES, SET_CURRENT_GAME } from "../actionTypes";

const initState = {
    current: {},
    list: []
}
const game = (state = initState, action) => {
    switch (action.type) {
        case LOAD_GAMES:
            return {
                            ...state,
                            list: action.games
                        };
        case SET_CURRENT_GAME:
            return {
                            ...state,
                            current: action.game
                        };
        default:
            return state;
    }
};

export default game;

Чем в GameDetails

function mapStateToProps(state) {
    return {
       game: state.games.current
    };
}

И в том же GameList

function mapStateToProps(state) {
    return {
       list: state.games.list
    };
}
...