markerikson / marks-dev-blog-comments

Comments for my blog
4 stars 0 forks source link

Practical Redux, Part 11: Nested Data and Trees #45

Open utterances-bot opened 3 years ago

utterances-bot commented 3 years ago

Practical Redux, Part 11: Nested Data and Trees · Mark's Dev Blog

https://blog.isquaredsoftware.com/2018/01/practical-redux-part-11-nested-data-trees/

chris-steele commented 3 years ago

Thanks very much for this series. Despite a few years passing it is immensely helpful and versatile (with one tweak)...

I ran yarn upgrade and everything seemed to be working fine. I then ran yarn upgrade --latest to take React to v17 and Redux to v4 etc, but had problems with the absolute paths. It took me an embarrassing amount of time to figure out, but in the end supplying a jsconfig.json file with the following fixed the problem:

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}

Seems like the .env trick is no longer supported by CRA. Just thought I'd mention in case it helps others.

markerikson commented 3 years ago

Hey, appreciate the feedback!

Yeah, obviously a good chunk of the info in this post series is now outdated. I'd write a lot of the Redux logic very differently today (Redux Toolkit, single-file "slices", hooks instead of connect, etc), and a lot of the ecosystem has evolved too (no .env option, Redux-ORM's API changing dramatically, and for that matter Semantic-UI being basically unmaintained).

At the same time, a lot of the principles I described in this series are still relevant: optimizing re-renders based on comparisons, selecting data from the store based on ID, the "modals" technique, splitting reducers.

I wish I had time to go back and update this series, but most of my attention these days is focused on rewriting the actual Redux docs themselves:

https://github.com/reduxjs/redux/issues/3592

In any case, always love hearing that the material I've written is helping folks!

chris-steele commented 3 years ago

Thanks for the quick reply! Throughout reading your series I wondered what you might do differently today. You mention using single-file "slices" and having read the current Redux Essentials guide it led my beginner's brain to ask whether you might try and use createSlice with Redux-ORM.

I saw you'd responded to a similar question on SO and pointed out that ORM provides its own immutability solution and so you don't get the benefit that Immer provides through use of createSlice.

Could I ask, would you still use ORM if you were to rewrite the series with the Minimek example?

For context, I'm starting out on a project that has relational data and a requirement for editing 'draft data', so I'm somewhat hesitant to deviate from the great example you set with Minimek 😅

markerikson commented 3 years ago

Honestly, I would probably go without Redux-ORM at this point. At the time that I wrote this, there were three reasons to look at using Redux-ORM: 1) automatic normalization, 2) easier immutability than spread syntax, 3) automatic handling of relational data

Now that RTK exists and has createEntityAdapter, that at least handles the "normalize items" and "easier immutability" cases. However, createEntityAdapter doesn't do anything for handling relations. So, if you have truly relational data and are always needing to look up relations all the time, then yes, Redux-ORM would still be able to help with that part.

chris-steele commented 3 years ago

I've given a few days careful consideration to my data, its relations and how I will use it. I'm getting the impression that it isn't sufficiently complex to benefit from using Redux-ORM. I found myself really wanting to use it, but my data is quite straight-forward and I'm dealing with only one-to-many relations with nesting of 3/4 levels. I will be normalizing the data, but something I still haven't been able to answer for myself is the question:

"How flat should my state be?"

It maybe misinterpretation, but I feel like any nesting is bad and flat is better.

To give a concrete example, I have a model which represents a multiple choice question. The model has a child array of items which represent the options that each question will present to the user. Each item has a string and a boolean (indicating whether the option represents a correct response) plus potentially some other minor properties. I wanted to normalize the array of items and set it up in the state as a sibling to the question models, e.g:

// state
entities: {
  multipleChoiceQuestions: {byId, allIds},
  multipleChoiceQuestionItems: {byId, allIds}
}

// example question
{
  id: 'cuid1',
  title: '...',
  items: ['cuid2', 'cuid3', ...]
}

// example item
{
  id: 'cuid2',
  text: '...',
  shouldBeSelected: true
}

However, the items will only be referenced in one place (the parent question), so I wondered:

"Is there any need to normalize or can I just leave the items as an array nested within the question?"

I appreciate your time and assistance greatly.

markerikson commented 3 years ago

To some extent it's really up to you :) Which I realize is a cop-out answer, but it is very much dependent on your own application's data structures and needs.

To some extent keeping nested data around is less of a pain point or anti-pattern now that RTK makes it a lot easier to update that nested state with "mutating" syntax.

Generally, consider where that data needs to be accessed and how you need to go about updating it.