Ad

React Update Sibling Component

I'm confused about react hot updating components.

I've got something like this:


const SingleEvent = ({ event }) => (
  <>{event.status}</>
)

const EventDetails = ({ event, updateEvent }) => (
  <button 
    onClick={async () => {
      const data = await getAPIResponse(); // { status: 'open' }
      updateEvent(event.id, data)
    }
  >
    Update
  </button>
)

const List = ({ events, updateEvent, selectedEvent }) => {
  if (selectedEvent) {
    return <EventDetails event={selectedEvent} updateEvent={updateEvent} />
  }

  return (
    <>
      {events.map(event => <SingleEvent event={event}/>)}
    </>
  )
}

const Page = ({ initialEvents }) => {
  const [events, setEvents] = useState(initialEvents || []);
  const [selectedEvent, setSelectedEvent] = useState(null);

  const updateEvent = (eventId, data) => {
    setEvents(prevState => {
      const eventIndex = prevState.findIndex(
        element => element._id === eventId,
      );
      if (eventIndex === -1) {
        return prevState;
      }
      prevState[eventIndex] = {
        ...prevState[eventIndex],
        ...data,
      };
      return prevState;
    });
  };

  return <List events={events} updateEvent={updateEvent} selectedEvent={selectedEvent} />
}

In the <EventDetails /> component I'm updating one of the events (basically changing it's status). If API works fine, when I close the details (set the selectedEvent to null) everything is changing as it should. If I close the the details before getting the API response - nothing changed.

I've checked the updateEvent function, and it's performing the update, but the UI is not refreshed.

To be clear:

I Open the <EventDetails /> component, I'm pressing the button to update the event. The API should change its status. When I close the EventDetails I'm getting a List of <SingleEvent /> components. Every one of them displays the event.status.

If I close the EventDetails before getting response, status in SingleEvent is not updating. If I wait for the response everything works ok.

Ad

Answer

The problem was with the update method. Operating directly on prevState is not a good idea. After I changed the updateEvent function, everything works fine.

    setEvents(prevState =>
      prevState.map(event => {
        if (event._id === eventId) {
          return {
            ...event,
            ...updatedEvent,
          };
        }
        return event;
      })
    );
Ad
source: stackoverflow.com
Ad