yoyoy
yoyoy

Reputation: 395

Merging Objects in React State

I am receiving new data points in real time, and I am trying to use the react useState hook to update my data. There may be several hundred thousand points, so updates need to be efficient. The structure of my state looks roughly like this:

{
  "graph1": {
    "line1": [[x1, y1], [x2, y2],..., [x100, y100]],
    "line2": [[x1, y1], [x2, y2],..., [x200, y200]],
    "line3": [[x1, y1], [x2, y2],..., [x900, y900]]
  },
  "graph2": {
    "line1": [[x1, y1], [x2, y2],..., [x100, y100]],
    "line2": [[x1, y1], [x2, y2],..., [x200, y200]]
  }
}

Where the xi, yi are just floating point numbers. I receive updates in a similar format, for example:

{
  "graph1": {
    "line1": [[x101, y101]],
    "line3": [[x901, y901], [x902, y902]],
    "line4": [[x1, y1]],
  },
  "graph2": {
    "line1": [[x101, y101]],
  }
}

And I would like to update my state so that it looks like this:

{
  "graph1": {
    "line1": [[x1, y1], [x2, y2],..., [x101, y101]],
    "line2": [[x1, y1], [x2, y2],..., [x200, y200]],
    "line3": [[x1, y1], [x2, y2],..., [x902, y902]],
    "line4": [[x1, y1]]
  },
  "graph2": {
    "line1": [[x1, y1], [x2, y2],..., [x101, y101]],
    "line2": [[x1, y1], [x2, y2],...,  [x200, y200]]
  }
}

Is there an easier way to do this than with a mess of spread operators? i.e.

setGraphs(xs => ({
  ...xs,
  "graph1": {
    ...xs.graph1,
    "line1": [...xs.graph1.line1, ...new_data.graph1.line1],
    // etc
})

In particular, with the spread operator approach, it's not clear to me how to handle a dynamic set of keys - for example, the new "line4" key in the update above.

I have full control over both the structure of the data and the structure of my react code, so if there is a more idiomatic way to achieve the same goal I would love to hear that too.

Upvotes: 1

Views: 54

Answers (2)

technophyle
technophyle

Reputation: 9128

You could regenerate the state and reset it. Your solution only works when you know all the possible keys but otherwise, we need to merge them by iteration. Like this:

setGraph(graph => {
  Object.keys(newData).forEach(g => {
    Object.keys(newData[g]).forEach(l => {
      if (graph[g][l]) {
        graph[g][l] = [...graph[g][l], ...newData[g][l]);
      } else {
        graph[g][l] = newData[g][l];
      }
    });
  });
  return graph;
});

Upvotes: 2

mohamed ibrahim
mohamed ibrahim

Reputation: 583

Spread operator is the best way to update objects or arrays. One of the new features in ECMA Script 2015 and above.

Upvotes: 0

Related Questions