0

I am trying to make an API request using Axios in React-Redux environment. On the console everything seems to be fine, however if I try to access any of the data I either get undefined or empty array.

This is my component:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { discoverMovie } from '../actions'

//Home component 
class Home extends Component {

  //make request before the render method is invoked
  componentWillMount(){
    this.props.discoverMovie();
  }

  //render
  render() {
    console.log('movie res ',this.props.movies.movies.res);
    console.log('movie ',this.props.movies);
    return (
      <div>
        Home
        movie
      </div>
    )
  }
};

const mapStateToProps = (state) => {
  return{
    movies : state.movies
  }
}

export default connect(mapStateToProps, { discoverMovie })(Home);

This is my action

import { DISCOVER_MOVIE } from '../constants';
import axios from 'axios';


//fetch movie
const fetchMovie = () => {
  const url = 'https://api.themoviedb.org/3/discover/movie?year=2018&primary_release_year=2018&page=1&include_video=false&include_adult=false&sort_by=vote_average.desc&language=en-US&api_key=72049b7019c79f226fad8eec6e1ee889';
  let result = {
    res : [],
    status : ''
  };

  //make a get request to get the movies 
  axios.get(url).
    then((res) => {
      result.res = res.data.results;
      result.status = res.status;
      return result;
    });

  //return the result after the request
  return result;
}

//main action
const discoverMovie = () =>{
  const result = fetchMovie();
  //return the action
  return {
    type : DISCOVER_MOVIE,
    payload : result 
  }
}

export default discoverMovie;   

This is the reducer

    import { DISCOVER_MOVIE } from '../constants';

//initial state

    const initialState = {
      movies : {},
      query : '',
    };

    //export module
    export default (state = initialState, actions) =>{
      switch(actions.type){
        case DISCOVER_MOVIE : 
          return {
            ...state,
            movies : actions.payload
          };
        default : 
          return state;
      }
    }

this is the log that I get from the console Log as you can see if I log the entire object I see all data, however if go deep and try to access the result I either get an undefined or an empty array and using redux-dev-tools I noticed that the state does not contain any value.

dev-tools

I read on internet including this portal similar issue but could not find any solution for my issue.

Solution

From official docs:

You may use a dedicated status field in your actions

Basically you need to dispatch action for each state to make an async action to work properly.

const searchQuery = () => {
  return dispatch => {

    dispatch({
      type : 'START',
    })

    //make a get request to get the movies 
    axios.get(url)
      .then((res) => {
        dispatch({type : 'PASS', payload : res.data});
      })
      .catch((err) => {
        dispatch({type : 'FAILED', payload : res.error});
    });
  }

1 Answer 1

2

With redux-thunk it's pretty simple to set up. You just have to make some changes to your store. Out the box, I'm pretty sure redux isn't the most friendly with async and that's why thunk is there.

import { ..., applyMiddleware } from "redux";
import thunk from "redux-thunk";
...
const store = createStore(reducer, applyMiddleware(thunk));
...

Then in your action you'll need to return dispatch which will handle your logic for your axios call.

const fetchMovie = () => {
  return dispatch => {
    const url = //Your url string here;
    axios.get(url).then(res => {
      dispatch(discoverMovie(res.data.results, res.status);
    }).catch(err => {
       //handle error if you want
    });
  };
};

export const discoverMovie = (results, status) => {
  return {
    type: DISCOVER_MOVIE,
    payload: results,
    status: status
  };
};

Your reducer looks fine, though with the way my code is typed you'll have status separately. You can combine them into it's own object before returning in discoverMovie, if you need status with the results.

This is my first answer on stack so let me know if I can clarify anything better!

Sign up to request clarification or add additional context in comments.

3 Comments

I am already using redux-thunk as a middleware. however i trying to follow the code above I get no data from the request.
I see. I made some mistakes in my code - if you copied and pasted from it please try it again. dispatch(discoverMovie(...)) was misspelled and I had payload: result instead of the correct: payload: results. ALSO, maybe this is the issue, I just reread your question: props.movies.movies is nothing. It should be props.movies.res and just map out from there. Check that?
I noticed the typo, but that was not the issue nor the payload. The issue is that I get no data from the action

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.