0

I am trying to build ERP application using React frontend and I have not found decisive answer whether to use object graphs in React state?

E.g. I would like to build Invoice view and I have the following domain model (provided here partially):

Invoice
   Person
      DeliveryAdsressArray
         DeliveryAddress
   Warehouse
   InvoiceLine
      Article

One should take into account that one article can appear in the several InvoiceLine's of the same Invoice and that is why it is wise to keep reference to one Article instance.

Any other framework (e.g. JavaEE with entity beans backend and facelets frontend) highly recommends to stick with OO object graphs. E.g. there are even Graph QLs, API can be automatically build from normalized DB structure that respects the object graph of particular design.

But React is highly inconclusive about this. E.g. official documentation https://beta.reactjs.org/learn/choosing-the-state-structure is explicitly contradictory regarding use of object graph vs flat structure.

From the one side it recommends normalization and hence object graphs:

Removing redundant and duplicate data from state helps ensure that all its pieces stay in sync. This is similar to how a database engineer might want to “normalize” the database structure to reduce the chance of bugs.

From the other side it is against object graphs and recommends flat structure:

Avoid deeply nested state. Deeply hierarchical state is not very convenient to update. When possible, prefer to structure state in a flat way.

To be true - normalization and flat format storage do not contradict one another: DB relations can be normalized, but yet they are stored in the flat tables. So, it is possible to store object data in the React state as flat arrays.

But what about nice references in the GUI?

I would prefer:

for invoiceLine...
   <div>{invoiceLine.article.name}</div>

instead of of:

for invoiceLine...
   <div>{articles[invoiceLine.articleId].name}</div>

Coming from the OO culture I would prefer former approach over later approach. From the other side, maybe the later approch (using flat arrays in the state) is not bad at all? And I just shold be mindful of my biases and abandond them in favour of best practices of the framework which I have selected for my project?

And decision about the shape of React state is highly connected with API design for the backend application. Whether API should reflect the object graph vs flat approach or there should be converter that converts API data from the one format into other format that is used by React state.

Of course, in every case there can be solution and I can work and stick with any approach, but I am interested in the optimal achitecture.

Of course, there can be hybrid approach, e.g. Invoice.Person subgraph could be stored as the object graph but DeliveryAddresses (if needed at all) can be stored in additional arrays in the flat way. Not nice, but JavaEE Entities also supports lazy loading which can prevent loading of deeply nested nodes and leaves of the object graph.

We can drive to dig into the cause of such inconclusiveness. I may guess that object graph approach is certainly the best choice for building maintainable and extendable app, but one should reject it and stick with (normalized) flat storage (in the React state) to support the efficiency both 1) the update of the state; 2) the update of the GUI.

E.g. if we need to update the price of one invoiceLine, then we are required to copy-update entire object graph (object tree). This can be done with the nice syntax of the spread notation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax, but still, it can be computationally constly. And the cost of the same amount happens during GUI update - React detects that entire object tree has been updated and it should check at what node/leave the changes have really happened and then update GUI.

If we have fine-grained and flat state, then the update of the state and its propoagation to the GUI is far less costly.

So - one should ignore urge to create nice and maintainable code and stick with code that is efficient. But programming evolves in the way that developers tend to add sugar to their code and that means that there can be libraries that allows "sugarized" object graphs in the code, but at the same time stores them into flat format in the state. So - maybe there are such libraries? Or some programming syntaxes?

What is the current state of reasoning in the debate about shape of React state? Object graph vs. (normalized, fine grained) flat storage? Which shape is more maintainable and which one is more efficient? And if there is maintainability/efficiency misalignment, then is there any library/approach/syntax that takes care of such misalignment?

My question is a bit complex, but many design questions are and Software Engineering is the site for them.

2
  • It can be good idea to use flat storage/shape for the state but have interface around it. Such interface can represent the state as the object tree. The writing would be OK. But I am not sure whether I can use this interface in the React JSX? I guess, that React rendering would not be capable to identify just only part of the GUI tree has changed. Most likely React would travel entire GUI tree and try to detect changes in this case as well.
    – TomR
    Commented Mar 1, 2023 at 8:08
  • Actually React already has such "interaces" for reading state data - and they are called selectors. So, it should be possible that React already does smart update when GUI refers to selectors... And maybe selectors can be made to look like OO/object trees.
    – TomR
    Commented Mar 1, 2023 at 8:22

1 Answer 1

0

The perfect answer is given in the book https://theroadtoenterprise.com/books/react-the-road-to-enterprise in the chapter about modern Redux Toolkit (RTK) and state management and the tool https://redux-toolkit.js.org/api/createEntityAdapter is explored as well. The idead is that the object graph should be stored in the Redux state in the form of the distinct arrays of entities, something like data are stored in normalized relational database tables. And RTK has tools (e.g. already mentioned createEntityAdapter which generates reducers/selectors) for supporing this. So, yes, this book advises against storing object graphs and deep nested structures in the states and it explicitly mentions that update of the leaves of such structures can invoke the update of GUI that refers to the entire object graph.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.