I have a simple Java Spring application that uses server sent events to send data to a frontend React app. Here is the how the backend is written:
@GetMapping(value = "/plot", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux get() {
return Flux.interval(Duration.ofMillis(1000))
.map(interval ->
currentStateMapper.map(eventRepository.getAll()).stream()
.map(plotDataMapper::map)
.collect(Collectors.toList())
);
}
What this does is probably less important but the idea is that I store recent events and the repository feeds me all of the events stored (they are stored in an infinispan cache), and then i use some mappers to get the current state and then to map it to objects suitable for visualizing with a XY plot.
It should send a message with the plotting data to the frontend every second. And when I open the endpoint with my browser (Chrome) it works like a charm. can see a new JSON appearing every second. But when I use React's event source to receive the messages instead of 1 message each second I get 6 identical messages each second. Here is the frontend implementation:
const Component = () => {
const plotDataEventSource = new EventSource(
"http://localhost:8080/tags/plot/antenna"
);
useEffect(() => {
plotDataEventSource.onmessage = e => {
console.error(e)
setData(prevState => {
/* some data handling */
return newState;
});
};
});
return ( /* html with plot */ );
}
And so the console.error() gets logged 6 times each second, identical objects. What can be the reason of this behavior?
useEffect will trigger the callback on each render - if you want it to behave like componentDidMount you should pass an empty array as the second argument.
The second argument is an array of values (usually props):