Udders
Udders

Reputation: 6976

react and redux data from axios not available in props

I am trying to get my head around React & Redux,

I am fetching some data from an api that I have written, and trying to render that data into one of my components. The data returned is a simple JSON object that looks like this,

{
"brief": "No brief given",
"tasks": [
    {
        "_id": "5c74ffc257a059094cf8f3c2",
        "task": "XXX Task 7",
        "project": "5c7458abd2fa91567f4e4f03",
        "date_created": "2019-02-26T08:58:42.260Z",
        "__v": 0
    }
],
"_id": "5c7458abd2fa91567f4e4f03",
"owner": {
    "_id": "5c5af553eea087426cd5f9b9",
    "name": "Test test",
    "email": "[email protected]",
    "avatar": "placeholder.jpg",
    "password": "$2a$10$dsGdQZ4APnmAVjbII4vX4u7bCEm0vjxGtHAJ8LijrcBBNTHSn9d5i",
    "created_at": "2019-02-06T14:55:15.321Z",
    "__v": 0
},
"name": "XXX Project 1",
"status": "Pending",
"slug": "XXX-project-1",
"created_at": "2019-02-25T21:05:47.643Z",
"__v": 0

}

I retrieve this data via an action in my componentDidMount() function in my component like this,

       import React, { Component } from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import { getProject } from "../../actions/projectActions";
import Dropdown from "react-dropdown";
import Avatar from "../profile/Avatar";
import ProjectPlaceholder from "../../img/new-project.svg";

import "react-dropdown/style.css";
import "../../css/project.scss";

class Project extends Component {
  constructor() {
    super();
  }

  componentDidMount() {
    const { id } = this.props.match.params;
    this.props.dispatch(getProject(id));
  }

  render() {
    console.log(this.props.project.name)
  }

Project.propTypes = {};

const mapStateToProps = state => ({
  project: state.project.project,
  errors: state.errors
});

export default connect(mapStateToProps)(Project);

This is my action,

    import axios from "axios";

import { GET_PROJECT, GET_ERRORS } from "./types";

// Set logged in user
export const getProject = slug => dispatch => {
  axios
    .get(`/api/projects/${slug}`)
    .then(res => {
      console.log(res);
      dispatch({
        type: GET_PROJECT,
        payload: res.data
      });
    })
    .catch(err =>
      dispatch({
        type: GET_ERRORS,
        payload: err.response.data
      })
    );
};

and here is my reducer,

    import { GET_PROJECT } from "../actions/types";

const initialState = {};

export default function(state = initialState, action) {   
    switch (action.type) {
        case GET_PROJECT:
            return {
                ...state,
                project: action.payload
            };
        default:
            return state;   
    } 
}

So 1) I cannot work why in my mapToProps function I need to using state.project.project when all that gets returned is JSON object, and 2) why in my render method the console.log logs undefined?

Can anyone help me please?

Upvotes: 0

Views: 441

Answers (1)

Praveen Rao Chavan.G
Praveen Rao Chavan.G

Reputation: 2860

1. I cannot work why in my mapStateToProps function I need to using state.project.project when all that gets returned is JSON object

You always need to access it has state.project.project because state is something which is injected by connect and project is your data slice name in the store, so you need to specify which is the data slice you would like to fetch the data from, because you have used combineReducers in store.

2. why in my render method the console.log logs undefined.

This is because of your initialState in your reducer is { } and you are filling this using an async call in componentDidMount, when render() gets it it's undefined.

Upvotes: 1

Related Questions