Reputation: 21
I have some problems with my React/Redux app. I'm successfully getting data from API, and when I take a look into Redux dev tools I can see that Redux is setup successfully, but I can't still get that data on React part. Here is my Games.js actions part:
import {
GET_GAMES_PENDING,
GET_GAMES_SUCCESS,
GET_GAMES_FAILED,
GAMES_DATA,
} from "../../constants/ActionTypes";
import axios from 'util/Api'
export const requestGames = () => {
return (dispatch) => {
dispatch({ type: GET_GAMES_PENDING });
axios.get('/games',
).then(({ data }) => {
console.log("Games data: ", data);
if (data.result) {
dispatch({ type: GET_GAMES_SUCCESS});
dispatch({type: GAMES_DATA, payload: data.games});
} else {
dispatch({ type: GET_GAMES_FAILED, payload: data.error });
}
}).catch(function (error) {
dispatch({ type: GET_GAMES_FAILED, payload: error.message });
console.log("Error****:", error.message);
});
}
};
As you see I have console.log to see if it is returning any data, and it is returning succesfully.
And this is index.js where I export my all actions:
export * from './Setting';
export * from './Auth';
export * from './Common';
export * from './Games';
Here is the Redux part of Games.js file:
import {GAMES_DATA} from "../../constants/ActionTypes";
const INIT_STATE = {
games: [],
isPending: true
};
export default (state = INIT_STATE, action) => {
switch (action.type) {
case GAMES_DATA: {
return {
...state,
gamesList: action.payload,
};
}
default:
return state;
}
}
And this is how I combine my reducers:
import {combineReducers} from "redux";
import {routerReducer} from "react-router-redux";
import Settings from "./Settings";
import Auth from "./Auth";
import Common from "./Common";
import Games from "./Games";
const reducers = combineReducers({
routing: routerReducer,
settings: Settings,
auth: Auth,
games: Games,
commonData: Common,
});
export default reducers;
All untill now is working fine (I think), but here is the part where is returning an undefined of gamesList:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { requestGames } from '../../appRedux/actions';
const mapStateToProps = (state) => {
return {
gamesList: state.requestGames,
}
}
const mapDispatchToProps = (dispatch) => {
return {
onRequestGames: () => dispatch(requestGames())
}
}
class App extends Component {
componentDidMount() {
this.props.onRequestGames();
}
render() {
const { gamesList, isPending } = this.props;
console.log("here it is" + gamesList);
return (
<div className='tc'>
{gamesList}
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
As you see I'm trying to console.log gamesList but it's giving like here it isundefined
. I don't have enought experience to set everything up, but still I would like to foreach that data in that file, how to do that?
Here is how backend returns /games:
{
"result": true,
"games": [
{
"id": 1,
"panelgameid": 71,
"img": "https://cdn.wallpapersafari.com/67/50/EkSo4r.jpg",
"name": "Counter-Strike 1.6",
"active": 1,
"minslots": 12,
"maxslots": 32,
"slotincreament": 2,
"order": 1,
"prices": [
{
"id": 1,
"gameid": 1,
"location": "Serbia",
"price": 0.6
},
{
"id": 2,
"gameid": 1,
"location": "Germany",
"price": 0.4
}
]
}
}
How to foreach that data?
Upvotes: 0
Views: 763
Reputation: 20047
In your reducer you set an initial state of:
{
games: [],
isPending: true
}
Then when your GAMES_DATA
reducer is hit you set gamesList: action.payload
where action.payload
is your games
property you see in console.log()
.
In your current code, your state in the Games
section would end up looking like this after your reducer is called.
{
games: [],
isPending: true,
gamesList: <the data you want>
}
It's possible you meant to set your action.payload
to the games
property in your state. If so you'd want to change your reducer function to be:
case GAMES_DATA: {
return {
...state,
games: action.payload,
};
}
When I look at your combine reducers, you set a property games
to be the result of your Games
reducer, so you'd need to access state.games.gamesList
in mapStateToProps
like this
const mapStateToProps = (state) => {
return {
gamesList: state.games.gamesList
}
}
(or if you meant to set games
in the reducer, you'd access state.games.games
)
There are a couple of other areas where things might fall over but it's hard to tell exactly from your snippets.
EDIT:
In answer to you React render issue, your current code tries to output a whole object which you can't do. You must access the properties in your game object and put them into some HTML (or just a string!) to tell React how to show them.
As an example, something like:
render() {
const { gamesList, isPending } = this.props;
return (
<div className='tc'>
<ul>
{gamesList.map(game => <li>{game.name}</li>)}
</ul>
</div>
);
}
Upvotes: 2
Reputation: 83547
As you see I'm trying to console.log gamesList but it's giving like
here it isundefined
Work backwards from there. gamesList
is assigned here:
const { gamesList, isPending } = this.props;
This means that this.props.gamesList
is undefined. Working backwards one more step shows that this.props
gets its value from mapStateToProps()
:
const mapStateToProps = (state) => {
return {
gamesList: state.requestGames,
}
}
But your Redux state doesn't have any key named requestGames
.
To fix the problem, change your mapStateToProps()
to set the gamesList
prop to the appropriate piece from state. It is difficult to guess what that might be from what you have provided.
Note that you can find issues like these with some debugging. This is an important skill to learn while you are learning to code. Read this article for some tips that can get you started. You should install the React and Redux developer tools plugin in your browser so that you can inspect props and state.
Upvotes: 3