服务器发送的事件在传入 React 时被倍增
Server sent events being multiplicated when incoming to React
我有一个简单的 Java Spring 应用程序,它使用服务器发送的事件将数据发送到前端 React 应用程序。下面是后端的写法:
@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())
);
}
它的作用可能不太重要,但我的想法是我存储最近的事件,存储库为我提供所有存储的事件(它们存储在 infinispan 缓存中),然后我使用一些映射器来获取当前状态,然后将其映射到适合使用 XY 图进行可视化的对象。
它应该每秒向前端发送一条带有绘图数据的消息。当我用浏览器 (Chrome) 打开端点时,它就像一个魅力。可以看到每秒出现一个新的 JSON。但是当我使用 React 的事件源接收消息而不是每秒 1 条消息时,我每秒收到 6 条相同的消息。这是前端实现:
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 */ );
}
因此 console.error() 每秒记录 6 次相同的对象。这种行为的原因可能是什么?
它缺少您的代码的一些重要部分,但是 re-render 可能会发生,因为您没有通知 useEffect
它应该 运行 在什么条件下,它可以通过 useEffect
方法中的第二个参数实现。
按照您的写法,useEffect
会在您的组件每次呈现时触发。如果你做了一个小的改变,将一个条件传递给 useEffect
它只会在那个条件改变时 运行。例如:
useEffect(() => {
plotDataEventSource.onmessage = e => {
console.error(e)
setData(prevState => {
/* some data handling */
return newState;
});
};
}, [data]); // <---- Assuming you are changing something called data.
当您的组件正在渲染时,useEffect
将比较 data
的值,只有当它发生变化时才会 运行。
useEffect 将在每次渲染时触发回调——如果你想让它表现得像 componentDidMount 你应该传递一个空数组作为第二个参数。
第二个参数是值数组(通常是props):
- 如果数组中的任何值发生变化,将触发回调
每次渲染后。
- 当它不存在时,回调总是会在每次
渲染。
- 当它是一个空列表时,回调只会被触发一次,
类似于 componentDidMount.
我有一个简单的 Java Spring 应用程序,它使用服务器发送的事件将数据发送到前端 React 应用程序。下面是后端的写法:
@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())
);
}
它的作用可能不太重要,但我的想法是我存储最近的事件,存储库为我提供所有存储的事件(它们存储在 infinispan 缓存中),然后我使用一些映射器来获取当前状态,然后将其映射到适合使用 XY 图进行可视化的对象。
它应该每秒向前端发送一条带有绘图数据的消息。当我用浏览器 (Chrome) 打开端点时,它就像一个魅力。可以看到每秒出现一个新的 JSON。但是当我使用 React 的事件源接收消息而不是每秒 1 条消息时,我每秒收到 6 条相同的消息。这是前端实现:
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 */ );
}
因此 console.error() 每秒记录 6 次相同的对象。这种行为的原因可能是什么?
它缺少您的代码的一些重要部分,但是 re-render 可能会发生,因为您没有通知 useEffect
它应该 运行 在什么条件下,它可以通过 useEffect
方法中的第二个参数实现。
按照您的写法,useEffect
会在您的组件每次呈现时触发。如果你做了一个小的改变,将一个条件传递给 useEffect
它只会在那个条件改变时 运行。例如:
useEffect(() => {
plotDataEventSource.onmessage = e => {
console.error(e)
setData(prevState => {
/* some data handling */
return newState;
});
};
}, [data]); // <---- Assuming you are changing something called data.
当您的组件正在渲染时,useEffect
将比较 data
的值,只有当它发生变化时才会 运行。
useEffect 将在每次渲染时触发回调——如果你想让它表现得像 componentDidMount 你应该传递一个空数组作为第二个参数。
第二个参数是值数组(通常是props):
- 如果数组中的任何值发生变化,将触发回调 每次渲染后。
- 当它不存在时,回调总是会在每次 渲染。
- 当它是一个空列表时,回调只会被触发一次, 类似于 componentDidMount.