1

I have an application which receives messages from a server every 1 second and via socket.io these messages are broadcast to a react component.

My react component is using a flux style architecture, so it calls an action when a message is received which adds (or updates) a record in a collection in a store.

My component monitors changes on the store and then updates the UI when it changes. In this case, it draws a marker on a map.

The problem is that due to the frequency of the updates my component redraws all markers every second, which I don't want.

I'm looking for an approach to allow my map component to respond to changes in a collection in a store, but not have the state update every second.

I thought I could have a collection for the raw data, and then only update the networkGPS collection selectively in my store, but the component seems to change based on any property in the store as they all seem to be part of its state.

In summary I'm looking to:

  • Collect data every 1 second in raw form and add this data to a store.
  • Bind a component to a collection in this store which I update only when changes require a UI redraw.

What I think I need to do:

Either:

  • Avoid putting the raw data into the state of the store (at the moment I'm unsure how to declare a collection which is not part of the state)

OR

  • Make my component more clever as to when it redraws, so it doesn't try to redraw on each state change.

I'm not sure which is the most appropriate solution for the problem, any info would be gratefully receieved.

Sorry if the question is a little unclear, I'm new to react / flux. Please do ask for any clarifications.

EDIT

At the moment I am getting round this issue by storing an array of the items (map markers in this example) I want my component to display in the component itself :( When the state changes and render is called, I intercept the state properties, decide if anything needs to change in the collection of markers and only amend them if needed. If no changes are needed, the collection in the component stays the same and no redraw is performed.

This is not ideal, I feel like I should be able to allow my component to respond to only specific state changes but I've not found it yet, still looking for a better answer.

dougajmcdonald
  • 19,231
  • 12
  • 56
  • 89
  • Could you elaborate on how "these messages are broadcast to a react component"? – shashi Sep 21 '15 at 13:11
  • Certainly, at the moment I have a connection to a 3rd party hardware component which has a 'data' event. On this event I parse the information on the server, build a sensibly formatted json object, and `io.sockets.emit(data)` the data. My react client listens to the socket.io message and when it receives data it calls an action method 'updateGPSData(data)'. This method pushes the data into a couple of arrays in a store. The arrays are part of the stores state, so when they are updated, my react component's state changes and the render method is called with the new data. – dougajmcdonald Sep 21 '15 at 13:52

2 Answers2

2

There are a couple of ways to approach this:

1) Use shouldComponentUpdate to compare old props and new props, re-rendering only the new marker states.

2) Switch to a cursor-based state tree that automatically triggers renders only for views that are bound to the specific parts of the state tree that have changed. I believe Baobab is one such library. See also Om (written in ClojureScript) and probably a number of other Flux implementations.

Given the impact of #2 my vote would be to go the route of #1.

glortho
  • 13,120
  • 8
  • 49
  • 45
  • Hi glortho, #1 was certainly an approach I was looking into although it seems only to let me decide if the whole component needs an update or not. Would you suggest perhaps using `shouldComponentUpdate` to decide if any of the records have changed, and if true, perhaps using the render method to loop over the collection and decide which records need to be moved / drawn? At the moment my render method just draws the entire collection. – dougajmcdonald Sep 22 '15 at 07:28
  • There are a couple of levels that shouldComponentUpdate could operate on. One is for the component that renders the collection as a whole, as you said. You can compare the old and new collection to see if anything has changed, though if nothing has changed the render functions should be relatively inexpensive anyway, since they won't touch the DOM. Or you can wrap individual markers in their own component and check old vs new marker in the shouldComponentUpdate method there. – glortho Sep 22 '15 at 11:28
1

I am not quite sure what's the problem that you face with updates every second.

However, the one place where you can queue the updates is between the socket.io and calling the action.

Instead of calling the action every second, you could queue the updates before sending it across to react.

shashi
  • 4,616
  • 9
  • 50
  • 77
  • The problem with the 1 second update is that I have say 100 markers on a map and I only want to update the rendering of perhaps 1 or 2 per second (based on properties of the data received). Whilst I could queue the data from socket.io, I do need to update the data in the store with other properties every second. Also, the incoming data is not something I control directly, so intercepting the messages and relaying them conditionally would incur additional processing and logic which I'd like to avoid if at all possible. – dougajmcdonald Sep 21 '15 at 13:46