Why can't my React app re-render eventhough I'm updating state?

So here is the context: I am currently working with an app that saves documents on a MongoDB database. My goal is to create a React app that displays in real time the newly inserted documents in the form of a list of events. Each new event must be on the top of this list.

The way I thought about it was that I could store an array in the state, and would add each new event at the start of this array. Then I would just take care of displaying the list in the EventList component by iterating through the array.

My problem is on the React part: for some reason my app isn't re-rendering eventhough I'm updating the state.

Before further explanation, here is my React code:

import React, { useState, useEffect } from 'react';
import './App.css';
import EventList from '../eventList/EventList.js'

function App(props) {
  const [events, setEvents] = useState([1, 2, 3, 'test']);
  const sse = new EventSource('http://localhost:3002/events', { withCredentials: false, 'Access-Control-Allow-Origin': 'http://127.0.0.1:3002/events' });

  function handleMessage(message) {
    setEvents([message, ...events]);
  }

  useEffect(() => {
    console.log('RENDERED');

    sse.onerror = (e) => {
      console.error();
      sse.close();
    }
    
    sse.onmessage = (e) => {
      handleMessage(e.data);
    };

    return () => {
      sse.close();
    }
  }, []);
  // EventList iterates through events to create <Event/> components with each index of the array
  return <EventList data={events} />
    
}

export default App;

So here, each time I get a new event, instead of the expected outcome: (with first event containing "foo" and second containing "bar")

  • First event emitted: events == ["foo", 1, 2, 3, "test"]
  • Second event emitted: events == ["bar", "foo", 1, 2, 3, "test"]

I'm getting:

  • First event emitted: events == ["foo", 1, 2, 3, "test"]
  • Second event emitted: events == ["bar", 1, 2 , 3, "test"]

Another weird thing is that events doesn't even seem to update but the displayed data does...

Can someone help me with this? I don't know why this won't render and I have not found how to solve this problem yet...

I did come across some different stackoverflow topics, but I feel like even though they looked a lot like my problem they couldn't help me solve it.

Btw, if you want to try it out and see the problem by yourself, here is the link of the repo: https://git.k-space.ee/rakbaal/camtiler/src/branch/wip (my app is on wip branch) Please know that this app uses your webcam but it doesn't do anything else than motion detection with it. You can access my React page at http://127.0.0.1

The command to start the app is docker-compose up --build

EDIT: I just found out why this failed. My goal here is to re-render everytime the events value changed, so I must add events in the array passed in the useEffect() hook for it to "listen" for change on events.

2 answers

  • answered 2022-01-25 15:15 Louis Coulet

    Every time your`component re-renders, it constructs a new EventSource. I suggest you move the instanciation of your EventSource inside the useEffect hook as such:

    useEffect(() => {
        console.log('MOUNTED');
    
        const sse = new EventSource('http://localhost:3002/events', { withCredentials: false, 'Access-Control-Allow-Origin': 'http://127.0.0.1:3002/events' });
    
        sse.onerror = (e) => {
          console.error(e);
          sse.close();
        }
        
        sse.onmessage = (e) => {
          handleMessage(e.data);
        };
    
        return () => {
          console.log('UNMOUNTED');
          sse.close();
        }
      }, []);
    

  • answered 2022-01-26 09:11 Babidi

    As shown in the EDIT section of my original post, the reason why my code didn't re-render is that I didn't specify events in useEffect()'s dependencies. I fixed the issue this way:

    useEffect(() => {
       // Code here
    }, [events]);
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum