Shaun Chua
Shaun Chua

Reputation: 713

Redux action call returns undefined then defined

currently working on a react redux project.

I was able to call my action fetchProjects() to handle an axios get request to the server.

Problem with my code is that it console logs as undefined before populating my state with my list of projects.

My goal is to render my list of projects on the screen upon calling the render function. But the component crashes as it renders undefined when I call this.props.projects.

Here is the component that calls the action fetchProjects.

import React, { Component } from 'react';
import Searchbar from '../../vp-ui/vp-searchbar/vp-searchbar.component.js';
import { connect } from 'react-redux';
import * as actions from '../../vp-services/projects/actions';
require('./vp-genecart.component.scss');

class GeneCart extends Component {

    constructor(props) {
        super(props);
        this.state        = { projects: [] };
        this.props.fetchProjects();
    }

    render() {
        console.log("h1", this.props.projects);
        return (
            <div>
                hello
            </div>
        )
    }
}

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

export default connect(mapStateToProps, actions)(GeneCart)

Here is the action that performs the get request

import axios from 'axios';
import history from '../../history';
import instance from '../instance';
import {
    PROJECTS_FETCH,
    PROJECTS_ERROR
} from './types';

export function fetchProjects() {
    return function(dispatch) {
        instance.get(
            `api/projects/`,
            {
                withCredentials: true
            }
        ).then((response) => {
                var projects = response.data.results;
                dispatch({
                    type: PROJECTS_FETCH,
                    payload: projects
                });
            })
            .catch((error) => {
                dispatch(projectsError('Couldn\'t get projects'));
            });
    }
}

Here is the reducer

import {
    PROJECTS_FETCH,
    PROJECTS_ERROR
} from './types';

export default function(state={}, action) {
    switch(action.type) {
        case PROJECTS_FETCH:
            return { ...state, projects: action.payload };
        case PROJECTS_ERROR:
            return { ...state, error: action.payload };
    }

    return state;
}

This is how it shows up on my screen enter image description here

Upvotes: 1

Views: 1422

Answers (1)

Bill
Bill

Reputation: 4646

The problem is that projects in your redux store really is undefined before the data is fetched. Therefore, if projects is supposed to return an array, you should set it to an empty array in the initial state.

const initialState = {
    projects: []
};

export default function(state = initialState, action) {
    switch(action.type) {
        case PROJECTS_FETCH:
            return { ...state, projects: action.payload };
        case PROJECTS_ERROR:
            return { ...state, error: action.payload };
    }

    return state;
}

EDIT: reading the comment, I think what you want to do is more likely something like this:

reducer

const initialState = {
    projects: null
};

component

render() {
    if (this.props.projects === null) return null; // Or a loading component
    return (
        // Your previous render code here
    );
}

Upvotes: 1

Related Questions