smooth97
smooth97

Reputation: 91

How to use api data passed through hooks using redux-thunk

I'm a beginner of redux. Importing api data into the console using redux-thunk and hooks into the component, but arrayed data is not available.

I'd appreciate it if you could help me figure out how to extract the data with a ui.

ActionContainer.jsx

import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchActionMovies } from '../store/actions/index';
import Movie from '../components/Movie';


const ActionContainer = (props) => {

    const dispatch = useDispatch();



    const actionData = useSelector(state => state.action);

    const [movies, setMovies] = useState(actionData);

    console.log(actionData);

    useEffect(() => {
        dispatch(fetchActionMovies());
    }, []);
    return (
        <div>
             { movies.map(movie => (
                <Movie img={movie.poster_path} key={movie.id}/>
            ))}

        </div>
    )
}

export default ActionContainer;

action/index.js

import axios from 'axios';

const API_KEY = '224ce27b38a3805ecf6f6c36eb3ba9d0';
const BASE_URL = `https://api.themoviedb.org/3`

export const FETCH_ACTION_MOVIES = 'FETCH_ACTION_MOVIES';

export const fetchActionData = (data) => {
  return {
      type: FETCH_ACTION_MOVIES,
      data
  }
}

export const fetchActionMovies = () => {
  return (dispatch) => {
    return axios.get(`${BASE_URL}/discover/movie?api_key=${API_KEY}&with_genres=28`)
      .then(response => {
        dispatch(fetchActionData(response.data))
      })
      .catch(error => {
        throw(error);
      })
  }
}

reducerAction.js

import { FETCH_ACTION_MOVIES } from '../actions/index';

export default function (state = [], action) {
  switch (action.type) {
      case FETCH_ACTION_MOVIES:
          return action.data
      default:
          return state;
  }
}

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import rootReducer from './store/reducers';
import './static/sass/style.scss';

const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(rootReducer, composeEnhancer(applyMiddleware(thunk)));

ReactDOM.render(
    <Provider store={store}><App /></Provider>,
    document.getElementById('root')
);

serviceWorker.unregister();

console.log(actionData) => (20) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

TypeError: Cannot read property 'map' of undefined

Upvotes: 0

Views: 2485

Answers (1)

tarzen chugh
tarzen chugh

Reputation: 11257

actionContainer.js

import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch, useStore } from 'react-redux';
import { fetchActionMovies } from '../actions/index'; // change path of action
import Movie from '../components/Movie';

const ActionContainer = (props) => {
    const dispatch = useDispatch();
    const actionData = useSelector(state => state.app.movies, []) || []; // you could use memoization to improve performance.

    useEffect(() => {
        dispatch(fetchActionMovies());
    }, []);
    return (
        <div>
            { actionData.results && actionData.results.map(movie => (
                <Movie img={movie.poster_path} />
            ))}
        </div>
    )
}

reducer/index.js

import { FETCH_ACTION_MOVIES } from '../actions/index';

export default function (state = [], action) {
  switch (action.type) {
      case FETCH_ACTION_MOVIES: // you should not mutate state
          return {
            ...state,
            movies: action.data,
        };
      default:
          return state;
  }
}

Hope that helps!!!

Upvotes: 4

Related Questions