Michael Porter
Michael Porter

Reputation: 229

React Hooks, useReducer not able to get state

I'm making a simple component try to make use of the useEffect and useReducer hooks. Everything seems to be working fine except that none of the items in the array actually make their way into the component. I've done some console.log statements inside the various functions and I can see that the API call is successful and that the data is available in the scope of the function under events. However, all that renders is an empty box. My code is:

import React, { useReducer, useEffect } from "react";
import "./App.css";

const  App = () => {
  const [events, dispatch] = useReducer(
      (state, action) => { switch (action.type) {
          case "fetchEvents":
              state = [ ...state, action.data];
             return state;

            case "removeEvent":
              return state.filter((_, idx) => idx !== action.idx);

            default:
                console.log(state);
              return state;
        }
      },
  []);

  useEffect(async () => {
    const response = await fetch("https://easynode-veohkvapci.now.sh/api/test");
    const data = await response.json();
    dispatch({type: "fetchEvents", data});
  },[]);

  console.log(events, 'log events');

  return (
      <div>
          {events.map((event, idx) => (
              <div key={event.event_url} style={{ border: "solid" }}>
                  <p>{event.name}</p>
                  <p>{event.date}</p>
                  <p>{event.description}</p>
                <button onClick={() => dispatch({ type: "removeEvent", idx})}>Remove Event</button>
              </div>
          ))}
      </div>
  );
};

export default App;

Should I maybe be calling useEffect inside of useReducer instead? I might be screwing something up that's supposed to happen in an async fashion.

Upvotes: 3

Views: 3386

Answers (1)

Tholle
Tholle

Reputation: 112787

The data you get in return from your request is an array, so you need to make sure you spread that as well in the fetchEvents case in your reducer.

const [events, dispatch] = useReducer((state, action) => {
  switch (action.type) {
    case "fetchEvents":
      state = [...state, ...action.data];
      return state;

    case "removeEvent":
      return state.filter((_, idx) => idx !== action.idx);

    default:
      return state;
  }
}, []);

Upvotes: 2

Related Questions