'Access useState previous state object's key value

Searched over stack overflow but found none similar (just replace an object key- value without using old value).

Consider a graph declared with useState

  const [graphBounds, setGraphBounds] = useState(graphBoundsInitialValue);

Where

const graphBoundsInitialValue = {
    left: Number.MAX_SAFE_INTEGER,
    right: 0,
    top: 0,
    bottom: Number.MAX_SAFE_INTEGER
};

Left and right are for X axis and bottom and top are for Y axis respectively.

I may have 1 or more graphs and for all of them I need to get minimum X, minimum Y, maximum X, maximum Y to display them correctly

I need to change one of the param of the graphBounds according to newcoming value from the server stored in graph variable and based on the old value of that param

I tried many things like

  setGraphBounds(prev => ({...prev, top : prev.top  > graph.maxY ? prev.top : graph.maxY}));

The issue is intellijIdea complains on that code and won't let me. I tried [] brackets and so on but with no luck.

I've ended something like this:

const updatedTop = graphBounds.top > graph.maxY ? graphBounds.top : graph.maxY;

let updatedBottom = graphBounds.bottom < graph.minY ? graphBounds.bottom : graph.minY || 0; // bottom domain always above zero
updatedBottom = updatedBottom > 0 ? updatedBottom : 0;

const updatedLeft = graphBounds.left < graph.minX ? graphBounds.left : graph.minX;
const updatedRight = graphBounds.right > graph.maxX ? graphBounds.right : graph.maxX;

setGraphBounds({top: updatedTop, bottom: updatedBottom, left: updatedLeft, right: updatedRight});

This code always runs when new data comes and compare new graph value with the old one.

Still got an annoying feeling of non-optimized code.

P.S.

BUT if I even dare to make it, it will be still non-optimized 4 calls (yeah, in a batch but whatever) like

for left: setGraphBounds(prev => ({...prev, left : prev.left > graph.minX ...

for right: setGraphBounds(prev ...

for top: setGraphBounds(prev...

for bottom: setGraphBounds(prev...

Any suggestion is appreciated. Thanks in advance



Solution 1:[1]

You may face some problems because you are not accessing the current state graphBounds, example here:

const updatedTop =
    graphBounds.top > graph.maxY ? graphBounds.top : graph.maxY;

The value of graphBounds is not always the current value.

By using callback instead of object you will have access to latest version of your state graphBounds:

setGraphBounds((graphBounds) => {
  const updatedTop =
    graphBounds.top > graph.maxY ? graphBounds.top : graph.maxY;

  const updatedBottom =
    graphBounds.bottom < graph.minY ? graphBounds.bottom : graph.minY || 0; // bottom domain always above zero
  updatedBottom = updatedBottom > 0 ? updatedBottom : 0;

  const updatedLeft =
    graphBounds.left < graph.minX ? graphBounds.left : graph.minX;

  const updatedRight =
    graphBounds.right > graph.maxX ? graphBounds.right : graph.maxX;

  return {
    top: updatedTop,
    bottom: updatedBottom,
    left: updatedLeft,
    right: updatedRight,
  };
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Soufiane Boutahlil