服务器发送的事件在传入React

时间:2019-06-29 11:48:57

标签: java reactjs spring-boot spring-webflux server-sent-events

我有一个简单的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次相同的对象。这种行为的原因可能是什么?

2 个答案:

答案 0 :(得分:1)

它丢失了代码的某些重要部分,但是可能正在重新渲染,因为您没有在应运行的条件下通知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的值,并且仅在其已更改的情况下运行。

答案 1 :(得分:1)

useEffect 将在每个渲染器上触发回调-如果您希望它表现为 componentDidMount ,则应传递一个空数组作为第二个参数。

第二个参数是一个值数组(通常是props):

  1. 如果数组中的任何值更改,则将触发回调 每次渲染之后。
  2. 不存在时,每次     渲染。
  3. 当列表为空时,回调将仅触发一次,     类似于componentDidMount。