React Native Radio

RNR 175: State Management In React Native

Episode Summary

In the second episode since the big relaunch, the new hosts of React Native Radio tackle the question of state management in React Native. Redux, MobX-State-Tree, context and hooks -- we cover it all!

Episode Notes

In the second episode since the big relaunch, the new hosts of React Native Radio tackle the question of state management in React Native. Redux, MobX-State-Tree, context and hooks -- we cover it all!

 

This episode brought to you by Infinite Red! Infinite Red is a premier React Native design and development agency located in the USA. With five years of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter), Infinite Red is the best choice for your next React Native app.

Show Notes:

If you missed it, read our blog post announcement about the React Native Radio relaunch in Red Shift: https://shift.infinite.red/relaunching-the-react-native-radio-podcast-716aa5f9310e

We're working on a transcript of this episode and all future episodes! Stay tuned for that.

Helpful Links:

Want to get to know the new hosts of React Native Radio? Follow them on Twitter! 

Make sure to subscribe on any the major podcasting platforms (search for "React Native Radio"). And follow us on Twitter at our new handle, @reactnativerdio.

Episode Transcription

Todd Werth:

Welcome back to React Native Radio Podcast, brought to you by Infinite Red. Episode 175, state management in React Native.

 

Jamon Holmgren:

Hey everyone. Welcome to React Native Radio podcast. I'm your host, Jamon Holmgren. And with me today are, uh, two of my co-hosts, uh, Robin Heinze, say hi Robin.

 

Robin Heinze:

Hello, everyone

 

Jamon Holmgren:

And Harris Robin Kalash.

 

Harris Robin Kalash:

Hey.

 

Jamon Holmgren:

Adhithi is not with us today. Sh- She's unavailable, but she will be back for future episodes. Uh, can't wait to have her back. This episode is, uh... W- we don't have a guest this episode, but we do have a really fun topic. Well, fun if you're a nerd like me, I love this topic, I gotta admit. This is, uh... This topic is gonna be about state management in React Native. Uh, we'll probably talk a little bit about state management React as well, uh, web, but, uh, but it's going to be primarily around React Native, given the topic of this podcast. So, uh, the... we're gonna talk about state management libraries. We're gonna talk about our experience working within each of these libraries, um, kind of our opinions around it, and, uh, also just kind of, you know, speculate a little bit about the future and, and what state management might look like in, in the future of React Native.

 

Jamon Holmgren:

Uh, I should mention that, uh, this episode is sponsored by my company, Infinite Red, and, uh, definitely check us out if you want any, of course, React Native work done. infinite.red is our domain. Uh, you can email me directly, jamon@infinite.red, if you have any questions at all. So without any further ado, let's, let's just dive into this. First off, I wanna ask my co-podcasters here, what is state management? Let's just start at the basics.

 

Harris Robin Kalash:

State management, you know, in any application where, especially in a client side application, where you have UI and a user interacting with it, you need to be able to manage the state of the world of that application, right?

 

Jamon Holmgren:

Right

 

Harris Robin Kalash:

In a, in a single place ideally. It just allows you to manage, like, what is the current world state of my application? Is the menu open, et cetera.

 

Jamon Holmgren:

Yeah. That's, that's a good way to, to say it Harris. It's like if you had, you know, like, like one of those hamburger buttons that opens a side menu, a drawer menu, is that menu open or is it closed? That's the state of it. That's, that's, you know, that's what it is. There are many different ways to approach this. This has been a problem or a, um, maybe not a problem, but it's been a, a thing in software development since the very beginning. Uh, Robin, do you have anything to add to like, you know, what you might define state management as?

 

Robin Heinze:

Yeah. Yeah. So I, I read in a blog post a while back, I wish I could remember who wrote the blog so I could give them shout out, but I can't remember.

 

Jamon Holmgren:

(Laughs)

 

Robin Heinze:

Um, but the, uh, state is a record of everything your user has done since opening the app or starting the app, stored in the form of basically an object or a data object.

 

Jamon Holmgren:

Very interesting.

 

Robin Heinze:

Um, so if they've opened menus, or loaded a list of things or whatever they've done, it's somehow captured in state.

 

Jamon Holmgren:

That's a really good, yeah, that's a really good way to say it. And in fact, I don't know if anybody listening to this podcast is as old as me, but, uh, way back when I was a kid, we had a car, I think it was a station wagon (laughs) that had a radio, and the presets, you could push the preset button in, like on the radio, uh, to switch to a different preset and the button would stay in, the one that you were on. So it'd be like, click this button, it would click out any others that were, that were, you know, currently pushed and it would pop over to the other ones. So you'd be like, oh, now I'm on 750, uh, news radio, you know, (Laughs) and you could set those, and whichever one was pushed in was the state. You could also look at the dial and see where the needle was and say, okay, that's the state, that's the, that's the station that I'm on, um, as being kind of like, that's my state. And like you said, Robin, that's that reflects what the user has done up to that point, because radio would just be on, you know, whatever the default was. If I, if I didn't push the button.

 

Jamon Holmgren:

But obviously we're talking about software here and, and specifically React Native. And when I did, uh, native mobile app development, uh, it was kind of, it was kind of interesting. I came from a rails background like Robin, you did. And a state often like in web development, especially when I did PHP, state was like reconstructed every single page load in the very beginning. So you would just go into your database and say, okay, hey, here's like, a cookie, you know, with a session token or something, who's currently logged in? Okay. Now that we know who's logged in, grab all of their current state, you know, like, uh, you know, a bunch of different things, plus certain amount of state would be held in the URL. You know, like what page are they on? Uh, what are they trying to do? Maybe there's like, a post action. So now we know what they're, what they're trying to do.

 

Jamon Holmgren:

So state was kind of scattered in a couple different places. Um, one of the big changes when I moved to mobile development, native mobile development was that state was, uh, it was, it was more stateful. It was like the variables would live on for longer, you know, like sit in a, in an object. And, and if you had a, like a drawer, you could just have like a class variable that would just track, you know, am I, am I open or am I closed? That was, that took a little different approach.

 

Harris Robin Kalash:

Yeah, I also, I think one thing that made a big change in sort of the paradigm is sort of, we used to have a fat, fat servers and thin clients, right? So now we have fat clients and thin servers.

 

Jamon Holmgren:

Right.

 

Harris Robin Kalash:

So our servers are, are ideally stateless, right? And really all the state is on the client side. And that's why, like, state management solutions today are much more important just because the client side has gotten so much more complicated than before, right?

 

Jamon Holmgren:

Exactly. Yeah. Yeah. That's totally true. And that, there's, there are reasons for that. There are reasons why, you know, we're pushing more and more over to the client. There's some resistance to that, there's some like, kind of throwback now to, like, can we throw, can we put stuff back on the server? I know Phoenix with Elixir, Phoenix has like Phoenix live, live view, which will hold all the state servers side and then push things to the client. But for the most part, you know, when you're building a React app or you're building a React Native app, most of your state is living client side on your, in your browser or in your, in your app. So, there there've been various, you know, approaches to this since React came out. Um, I remember in the very beginning, uh, Facebook, when they published React, also kind of came out with this thing. Uh, it was, it was called Flux. It was like the flux pattern. It wasn't so much a library, but it was more like a pattern of uni-directional data flow. Sorry. Were you going to say that?

 

Robin Heinze:

That's what I was going to say, yeah.

 

Jamon Holmgren:

Okay. (laughs) And, uh, it was, it was pretty confusing. And I don't know, I don't think Robin, you were working in React at that time.

 

Robin Heinze:

No, I was not at that time. My, my idea of state management was active record. (laughs)

 

Jamon Holmgren:

Active record, exactly. In, in rails.

 

Robin Heinze:

In rails, yeah.

 

Jamon Holmgren:

Yeah. And it was, it was actually really confusing. They had these like, charts and like, if you go look it up now, the charts have improved, the documentation has improved, but at the time, you looked at it and it was like, okay, here are a lot of new concepts. Here are a lot of things that, that I, that I don't understand, you know, things like reducers and, um, and actions, and it was kind of introducing a bunch of new terminology. It was also kind of explained in a certain, you know, it was just, it was just very kind of, uh, kinda computer sciencey and, and less practical, uh, for me. So, you know, and, and at the time we... I mean, talking about like active record, you know. When you were, when you would build a native app, you would use things like SQL Lite, uh, which is a very simple database built right into, you know, uh, iOS and Android.

 

Jamon Holmgren:

Um, you can also do things like push things into core data on iOS, and you could, you know, there, there were some other, some other options there too. Of course, maintaining things in, in memory as well. But often state was just kind of scattered all throughout the application. And so when we went to, to React and they came up with the flux pattern, it was an attempt to kind of centralize that state. We were using Amber at the time. And Amber has its own kind of way of, it was actually, uh, bi-directional data flow at that, at that point in Amber. Yeah, that was on the website. And, uh, so we really didn't get into React until Redux had already hold. So Redux was invented in, I think, or it was at least released in, I think 2015, which is, which was also the same year that React Native was released. And it was, it quickly took over as the, you know, the library and the pattern. 'Cause it was basically a simplified version of the flux pattern way simplified. It made sense. It was like, more, more obvious. Still had some of the same kind of downsides and stuff like that, but it did, you know, it implemented the flux, the flux model.

 

Jamon Holmgren:

And so let's, let's back up for a second. So we talked about like state being a record of everything that you've done, uh, in the app. So how does Redux, you know, handle that?

 

Harris Robin Kalash:

Redux lets you... so Redux, uh, has, uh, you know, like a single source of truth state tree. So you can think of it as like this giant object where that represents the entire state of your application, and it lets you modify it by using, uh, you know, reducers. So, w- what you're essentially doing is that you're passing in the entire state, modifying in, modifying it and making a copy of it, really, as you modify it. And returning a whole new state every single time, which sounds very, very inefficient. (laughs)

 

Robin Heinze:

Well, and also let's just talk about the, like, the word "reducer", like if I'm like new to React. I mean that, it doesn't mean anything to me I'm like. reducing what?

 

Jamon Holmgren:

Yeah.

 

Robin Heinze:

Like it's just not, it's not an intuitive concept.

 

Jamon Holmgren:

It's, it's very true. Um, it's, it's... I think in, uh, I think an Elm, which was either inspired by Redux or inspired Redux, I don't remember which direction that went.

 

Harris Robin Kalash:

Elm inspired Redux.

 

Jamon Holmgren:

Okay. Okay. So I did some Elm, uh, and Elm calls them updates, I think. You know, like, this is an update-

(laughs)

 

Robin Heinze:

Yeah. Which is-

 

Jamon Holmgren:

That makes more sense to me.

 

Robin Heinze:

Yeah. Yeah, it does.

 

Jamon Holmgren:

There's an update function, and you pass in the, uh, you know, the state, like Harris said, and any actions that you want to, you know, do on that state. And then it returns back a whole new object that represents the, uh, the state at that point. And then it can, and then it has ways using Redux React to propagate those changes to the components that need to be updated.

 

Harris Robin Kalash:

One, uh, big selling point of Redux at the time, I remember, was always like, this time traveling thing. It sounded really cool. But it comes down to... because you're, you're modifying the state every time and through an action, you're able to quickly implement like, an undo. You're able to like, go back in time, in your state basically. Since your state changes over time and that's recorded. Right, so.

 

Jamon Holmgren:

Yeah, implementing undo, where your state is just scattered into like the, this object and that object, is actually pretty tough. And then conversely, if you save everything into a SQL database, unless you take advantage of databases, you know, kind of inherent features of rollback and stuff like that. Um, it can also be difficult because, uh, you know, like, when did something change? How did it change? So, uh, so Redux really kind of nailed that. It's like, okay, we know what the previous state was because we have the previous state structure. We can hang onto it. Like, we're making new copies. So just hang onto the old one. And you can roll back that change. So, time travel, undo, redo, et cetera. It was, was pretty cool in, in Redux.

 

Jamon Holmgren:

And there are other, uh, you know, other things there too, like action creators. So like, uh, I wanna, I wanna... I'm triggering an action, so I need to create an action, which isn't... it, kind of, counter-intuitively, an action is not an object. It's not, like, an event. Um, it's not a function call. You know, you're passing an object through to your reducer. And then beyond that, you also have to think about side effects.

 

Harris Robin Kalash:

Side effects are, uh, events that are outside of the main flow for your application's functionality, and in turn, outside of your control.

 

Jamon Holmgren:

Yep. That makes sense. And a good example of this would be like, when you're calling out to an API. This is something that you don't control when it's, when it,  you control when it starts, but you don't control when it ends, and then how that is handled once it comes back. Uh, so you need some way to handle those side effects. Um, and, uh, so Redux has a few different ways of handling this. You know, we started, I think we tried Thunks, uh, which is like Redux Thunks. It was a certain way of approaching it. Thunks are probably the simplest way, arguably, to handle side effects in Redux, but, uh, they also lack a certain amount of power. There's kind of like, not really, uh, a way to handle multiple, you know, multiple things happening in kind of just flowing through, uh, like we're gonna, we're gonna send out this, this API request and then this other thing is going to happen. And, you know, we have to pop up a modal and, you know, like all these things kind of happening in conjunction with each other. So, we ended up moving to Redux Sagas, and that was the one that, that really stuck with us while we did Redux. Have either of you used a Redux Sagas?

 

Robin Heinze:

Yeah. I mean, I was obviously working with Sagas at Infinite Red during, during that period. Um, I've- I mean, I don't think I ever truly understood Sagas.

Robin Heinze:

I knew how to use them, but it felt like a lot of boiler plate to set up. And it was, it felt like you, like every time you added a saga, you needed to add some code in like, four different places in order to like, connect all the dots to make it actually fire when it needed to fire.

 

Harris Robin Kalash:

Yeah.

 

Robin Heinze:

So yeah, I just, I remember Sagas being confusing.

 

Harris Robin Kalash:

It also gets confusing when you have to run other Sagas in your Sagas and then it's like,

 

Harris Robin Kalash:

It's hard to keep track.

 

Jamon Holmgren:

Right? Yeah. And it kind of brings up sort of a broader theme within Redux. Uh, the, the complaint about boiler plate, because boiler plate is kind of one of the things that, when you first get into Redux, you're just like, wow, I'm, I'm touching a lot of files. I'm writing a lot of code just to do one thing. And I've heard it kind of, sort of described as Redux has sort of like, a steep learning curve, but then once you're up, kind of onto the plateau, then it's easy to scale applications up pretty much infinitely. So, you can get to a pretty large application, and the way that you add, you know, any sort of event or, or, you know, state is pretty similar to how you did in the beginning. Uh it's you know, you're not having to kind of manage something that gets more and more unwieldy as time goes on. So that's sort of the trade off there is that it's like a harder in the beginning, but easier as you scale or at least that's kind of how it's sold.

 

Robin Heinze:

Yeah. I can see that.

 

Jamon Holmgren:

Yeah. And, and, and that's, so that's, that's kind of a big deal. So let, let's, uh, let's kind of move on to some other options here. So, at Infinite Red, we got a little bit tired of Redux. We did a few things. Like we created, uh, Redux Sauce, which, you know, helps with, there's a lot of kind of helpers and stuff like that, to, you know, make Redux simpler. But once we got, you know, we had a few, quite a few apps under our belt, probably two years worth of it, of building apps using Redux. We started looking for something else, and that's when we encountered MobX, but specifically MobX-state-tree. And I gave a couple talks, actually three talks about MobX and MobX-state-tree last year. And, I'll just kind of, in brief, explain how, how they kind of work together. So MobX was created by Michel Weststrate. He now works at Facebook. He didn't before. And it's, uh, sort of a reactive engine that allows you to watch certain values. And when they change, it triggers functions. It just triggers like, a watcher. You're observing the values. Um, it's very, very slick. It's very small amount of code in, at Redux or, I mean, at a, sorry, at React Live Amsterdam, I actually watched Max Gallo, uh, he re-implemented MobX and MobX React, in like, 50 lines of code, on the stage.

 

Robin Heinze:

Wow.

 

Jamon Holmgren:

It was, it was, it was pretty impressive.

 

Jamon Holmgren:

It was a slightly naive version. But when I went and looked at the code that's actually under the hood, I- in MobX, and MobX React. It wasn't that much different. Like it was, there was, there was some additional edge cases and stuff that it handles. But it's a pretty simple system. Uh, but MobX by itself is pretty unstructured. Uh, so like, how do you use MobX? Well, how do you want to use it? (laughs) And that's not usually like, how programmers want to approach it, you know, like they want to have sort of a pattern. Like what is the best way to do this? And so MobX-state-tree kind of came out of, uh, kind of came out of that. And Michel created that. It makes MobX more like Redux, in the good ways, by creating kind of a global store, and the ability to run actions, which are just functions, just methods basically. And, uh, you can also create views, which are like computed, like you already have some properties in your, or some, uh, some data in your store and you just want a different view of it. Maybe it's sorted a different way. Maybe it's filtered a certain way.

 

Robin Heinze:

I use views a lot for things like users, full name, like first and last put together and address formatting and all sorts of things.

 

Jamon Holmgren:

Exactly. The data is already there. You don't want to like store it as a full name property, but you just need to access it once in a while to help put it in that way. So we use MobX, MobX-state-tree, and then another thing called MobX React light. MobX React Light, basically you just wrap a, uh, a component in an, in a function called observer, and it will observe any, any properties that are accessed from your store and from your models, in a component. And if those properties, and only those properties change, it will, re-render just that component or any that are observing that. And it makes it extremely performant. Now there are some downsides to MobX and MobX-state-tree and, and et cetera. Uh, but it's honestly extremely powerful just right out of the box.

 

Robin Heinze:

Yeah. You could get very, you can get pretty far just using the basics of MobX-state-tree. Um, when you get into, sort of, the more advanced features, like middleware and lifecycle events, it can get quite a bit more complicated, but it's also quite a bit more powerful, but you can, you can do a lot with just properties and actions and views.

 

Jamon Holmgren:

Yeah.

 

Harris Robin Kalash:

Yeah. One thing I love about MobX is how clean it keeps your views. Like, from my experience when using Redux, you always end up having views full of logic, just because it's just much more effort to go ahead and like, make that more dry. Like you have to go in and implement selectors. And with MobX it's just really easy. Like, the computer views are right there. It's just, ties in well together.

 

Robin Heinze:

Yeah. We're able to keep a lot of business logic in models, which are infinitely more testable. Uh, you can write unit tests for a lot of the logic that used to be sort of hidden in your component classes and it sort of separates the concern to the nice way.

 

Jamon Holmgren:

Yeah, totally. And you kind of touched on it, but like, how does MobX StateTtree handle side effects

 

Robin Heinze:

Flows. So, we're talking, I mean, like, flows are basically fancy async functions, or like, it's a wrapper around generator functions, I think technically-

 

Jamon Holmgren:

Right.

 

Robin Heinze:

But basically you call out to your API, and it'll wait till it comes back, and then do some more stuff with the result. It's pretty, it's pretty intuitive, especially in the JavaScript context. It's, we're all, we're already used to promises and waiting for things to complete. It basically builds on that.

 

Jamon Holmgren:

Yeah, a- and you can use like async functions as an, as an action. It would be more-

 

Robin Heinze:

Oh, I do, I do all the time.

 

Jamon Holmgren:

Yeah. And that's more like Redux Thunks, that's like, uh, on the order of Redux Thunks. You can do basically the same thing as Redux Thunks there. But then, there are some limitations like you hit a certain point, and the way that that code is sort of transformed, starts making it a little more awkward to wait for things. You know, if you're waiting for multiple things, then you can't like, manipulate properties directly and stuff like that. So when you do that, if you start hitting one of those limitations, you switch over to a Flow, which is just like, like, you wrap your, your, your phone, you make your function a generator function, which is basically just adding a star.

 

Jamon Holmgren:

Like an asterisk-

 

Robin Heinze:

Yeah.

 

Jamon Holmgren:

to the function. And then you wrap it in a function called Flow, which comes from MobX-state-tree, and then within that, instead of doing a wait, you do yield. And it's not much different than that. Like, I don't really think there's anything else to it. I think that's the majority of what you do.And then it becomes basically like you just write it, like you would write a story. You're like, I want to yield, I want to wait for this call. And then when it comes back, I want to do this other thing. And you can even yield for things like, I'm going to, um, I'm gonna, I'm gonna wait for, there's a function called Wait and you can wait for, like, a property in the model to change. So example, you can pop up a modal, and then when that modal closes, continue your action. You can just keep going, like in the middle of your action. It's, it's kind of almost freaky. Like, like it works this way.

 

Harris Robin Kalash:

I guess it's good to note maybe that, like, you don't actually have to use Flow. I've actually never used it in any of my apps.

 

Jamon Holmgren:

Yeah.

 

Harris Robin Kalash:

Um, I don't know why. I've never really found it... I think maybe it makes the code a bit cleaner in certain cases, but I've never understood why I should use it, to be honest with you.

 

Jamon Holmgren:

Yeah, no, totally. Um, and by the way we should mention, this is not the Flow that Facebook creates. That's like a TypeScript competitor, sort of static typing. Um, we're talking about a function. It's literally just a function from MobX-state-tree that you pull in, called Flow.

 

Robin Heinze:

Yeah. And after, what? Two... a year and a half, two years, of writing apps with MobX-state-tree, I almost always just use regular async functions. There's been very few occasions when it's necessary to go, to go further than that, which is even better, in my opinion.

 

Jamon Holmgren:

Yeah.

 

Robin Heinze:

It's just, it's just JavaScript. They're just functions.

 

Jamon Holmgren:

Yeah. So you don't have, like, you don't have to create an action. You just call a function. (laughs)

 

Robin Heinze:

Exactly. You have it-

 

Jamon Holmgren:

You'd give it some properties.

 

Robin Heinze:

It also works nicely in my brain because it's very object oriented. I- it calls back a lot to my Rails days because you're, you're creating, you have like model definitions and you have instances of your model and then you call action. Like you call like user dot load. Like you're, you're calling actions on your object. You're setting properties directly on your object. It's just very familiar.

 

Jamon Holmgren:

I wish that Adhithi was here because I think Adhithi, she, she's used Redux a lot more. She's, she probably would be able to provide a little different perspective on this. We have three MobX-state-tree fans here. Um, but with that said, what are some of the downsides to MobX-state-tree? And I'll actually start by saying, it's often kind of thought of as magic. Like, you know, you don't see exactly what's happening. Redux is basically a pattern that there's sort of a, a library wrapped around it. But it's, it's just a pattern. And so, everything you're writing feels like, you know, just normal JavaScript. Well, until you get into like, Sagas and Thunks and stuff, there's a lot of it. You have to touch a lot of files, but it just feels kind of like you, you can kind of follow it all the way through MobX, it's like, how did this, this component just re-render, you know? You don't necessarily know, unless you've actually looked into like, how they work under the hood.

 

Robin Heinze:

Yes. It is very, it is very much more, sort of magical, which can be frustrating sometimes if you're trying to debug a red screen or whatever. And speaking of red screens, that's, that's another common complaint of MobX-state-tree, is that it, it's a little bit brittle. It tends like, I- if you don't set your data in exactly the right way, like, objects will die, and then you get a red screen, and it can be pretty frustrating not to be able to just like, ah, I want to take this data and replace it with this data. And that's just what I want. But you have to sort of times keep track of your, the instances that you are observing and making sure to handle them appropriately if you're replacing them with new ones. And that could be a little bit finicky.

 

Harris Robin Kalash:

Yeah. And sometimes if you don't use it forces you in a direction where like, if you don't do that, it might bite you in the ass later. Because, for example, using references is something I've learned to start liking in MobX because if you have a bunch of data and you don't have a reference to it and you start modifying that, or you add it to the tree and it's like the same, it's the same data, it's going to complain. Or, kind of what Robin was saying, where if something doesn't exist in the State Tree anymore, data's going to complain, or, you know, you have to detach this object from the tree before you can add it in another part of the State Tree. I don't actually think you can have the same data on two parts of the State Tree.

 

Robin Heinze:

That's why, actually why I stopped using References, because sometimes I want to keep a copy of the data in a different place. And when they both have the same reference, you can't do that.

 

Harris Robin Kalash:

Yeah.

 

Jamon Holmgren:

Can you explain what a reference is to people who don't use MobX-state-tree?

 

Robin Heinze:

So a reference is like, if you're familiar with relational databases, it's like a primary key. It's basically like, a unique-

 

Jamon Holmgren:

The ID.

 

Robin Heinze:

Yeah, a guaranteed, unique identifier for a particular object.

 

Jamon Holmgren:

Right. And so, instead of storing the whole object on the tree, at that location, you would just store the ID. And then, MobX would smartly look at it and say, oh, this is an ID. Let me go find it in the rest of the tree. And they, it kind of looks around until it finds that identifier and then pulls that back and lets you use that, that particular object.

 

Robin Heinze:

It's good in theory. In practice, what I've run up against is that, like in mobile applications, you're not dealing with a single source of truth for your data, especially if you're, if you're getting data from an external API. Now, if your app is a standalone, and it's sort of managing its own data, that's probably another scenario and it might work better in that scenario. But if you're loading data from an API and it's like, paginated or anything like that, then you're not dealing with a full set of data. And so it's, as soon as you only have a partial set, one of your references is probably bad. So that's what I ran into a lot with references is that it really works best when you know you have a full set of data and you're, you are the single source of truth.

 

Jamon Holmgren:

I've gotten around that by storing the ID as like, with a prefix. So it'd be like, maybe for a user's list, I want everybody's ID. But then for my profile, I want, you know, profile dash my ID. And then I just store that separately. It's, it's not ideal. Um, it's something that, uh, th- that I, I, I have a lot of ideas around, but I think, you know, honestly we could probably do a whole episode just on MobX-state-tree. Uh, and we probably should, uh, to be honest, I think there's some really cool stuff there.

 

Robin Heinze:

What other libraries are there?

 

Jamon Holmgren:

Well, uh, let's, let's talk about just hooks and context. Like, let's start with, you know, just the what's built into React. So obviously React has its own state management to some degree. There's like, set state and then it turned into a used state later, with hooks. Uh, they also released th- the new version of React Context, which allows you to share a state down a whole tree of components. And I've, I've used that it'll, it's, it's pretty cool. You can, obviously hooks are, are kind of cool. They're, they're kind of fun to use. They're, they have certain rules around them, but they're not that hard to learn. And then you can just store your state right there in your component. It's right at your fingertips. There's very little code. You're ready to go. So what do y'all think about just using hooks and then moving data around your components, uh, using content?

 

Robin Heinze:

So I've never actually used just hooks and context, but my first question would be, how do you persist it between app loads? Since that's, that's, that's one of the benefits of using a more robust statemanagement, is that you can kind of plunk it in async and then rehydrate everything. Uh, what options do you have if you're just using context and hooks?

 

Harris Robin Kalash:

I guess you would have to do it individually, and that's not ideal. So, I completely agree with you, but you could, you could obviously have a bunch of providers for every piece of state and hooks that you have, that are persisting and re-hydrating their own states, right? Robin, like, um, to answer your question, uh, you would just a set item, like, I- in sort of that specific provider and like, sort of use state, or like, let's say you have like a sticky state, then you have like used sticky state, in that reusable, like, I guess used state function. Uh, hook, actually, the reusable hook. You could just keep persisting that specific piece of state the same way. It's just, you wouldn't be able to do it in one place for everything. You would have to, it will, it will be like everywhere in every like, hook that you have.

 

Jamon Holmgren:

Yeah. And, and one of the benefits of hooks is that you can, you can build these kind of modular, like, your own hooks. And you can say, used persistent state and then it persists it. And then in the future, just kind of loads it back in, which is kind of cool. 'Cause it's sort of a hybrid between... There, there is sort of a global place where this stuff is stored, and you can also just, like, you know, your used persistent state could just check, you know, async storage, for example. It could just check to see if this exists. Um slightly awkward though, and things like time travel wouldn't be as possible. Um, you know, uh, just, just kind of just, just, uh, it's, it's actually one of the inherent problems of storing state at the leaf, at the node edge, like right in the component itself.

 

Jamon Holmgren:

'Cause this is the problem, like in a game, for example, like you, you have a game and you have objects, and objects work particularly well in games because it's like, okay, you have a spaceship. And it has, it has a certain amount of health and it has like a speed and a direction and whatever. So, you know, that's fine. But then if you want to do a save game, (laughs) you have to like, go and collect all that data and then put it somewhere. And then when you restore, you have to then create things and like, manipulate the objects into the right spots. Where having like, a centralized store definitely helps with that. I think one of the bigger problems with hooks and context is, uh, performance, uh, because, you know, if, if you're not careful, uh, you'll, you'll just kind of reinvent Redux or you'll reinvent MobX-state-tree anyway, uh, when you're using context. And often you'll be in a position where you're rendering, you know, large chunks that you don't need to re-render.

 

Jamon Holmgren:

That's one of the benefits of using something like MobX React, where it just monitors one particular property and will only re-render that, that, that component when it needs to. But it's definitely, you know, you can do it, especially for smaller apps. You can definitely use hooks and context. We're, we're, we're pretty far into this episode. Let's, let's keep diving through some of the other, you know, options out there. So my business partner, Gant Laborde created a really cool GitHub Repo called React State Museum. Uh, you should go check it out. The... basically what it is, it, uh, it shows one, it's sort of like, TodoMVC, where they showed like, okay, all these different to-do apps in different frameworks. This is the same idea, but it's using a packing list instead of a to do list. Very creative. Uh, but, (laughs), uh, it shows examples in React.

 

Jamon Holmgren:

Uh, there are links to a GitHub repo. There are links to like, a code sandbox. So, you can go check it out. And React Native, in a lot of cases. You can check out like, an expo snack, or you can go look at the code itself. Just running through it, there's, like, a set state example, there's React 16 Context example. What we were just talking about. Of course there's Redux, there's MobX by itself without MobX-state-tree. There's, uh, MobX-state-tree, of course. And then there's Unstated, which is pretty popular. I think there might be Unstated Next, I'm not sure. Um.

 

Robin Heinze:

There is. Unstated Next is what uses hooks.

 

Jamon Holmgren:

Perfect. Yep.

 

Robin Heinze:

I don't know, I don't know if it's in the State Museum, but.

 

Jamon Holmgren:

Yeah. If not, you know, like feel free to submit a pull request out of curiousness.

 

Robin Heinze:

Yes, contributions welcome.

 

Jamon Holmgren:

Absolutely. You can go look at-

 

Robin Heinze:

Hey, and, Hacktoberfest is coming up, so.

 

Jamon Holmgren:

That's right. Yes. By the time you hear this, uh, Hacktoberfest may be already underway. So, that'd be a great way to, to, uh, to contribute. One thing we haven't talked about is using Graph QL, Apollo, um, you know, Apollo link state, et cetera. There are examples of that on, on the React State Museum. I'm, I think it's a cool concept. The idea of using Graph QL. It kind of is a little bit of a throwback, it's like throwing back to server, um, server state, basically, like we're going to store the state over there, and then we're going to just kind of seamlessly work between the server and the client side. There's also things like React Automata? Is that how you say that?

 

Robin Heinze:

Automata, I don't know.

 

Jamon Holmgren:

Automata (laughs) Uh, freeactl, peer store, React observable store, React Easy State, Rematch, Unistore. There are a lot of these that I actually haven't even heard of.

 

Robin Heinze:

I've- Yeah. I was going to say, I haven't heard of most of these. I had no idea. There were so many state management options.

 

Jamon Holmgren:

There are a ton. There are a ton. IMER, actually IMER, um, was created by Michel, the same guy that created MobX, and MobX-state-tree. And IMER is a very interesting, uh, that's that's it's it's um, well, w- we won't talk about IMER here, but it's, it's a very interesting approach. It's, it's definitely different than MobX. And then, uh, you can also look at lightweight versions of Redux and, and whatnot. And Recoil. Recoil is a new one that came out of a different part of Facebook, that solves a particular type of problem, especially around, like, really complex interactions and whatnot. So, uh, if you, if you had to work in a React, I think this is probably going to be kind of obvious, if you've listened to this episode, but, if you had to work in a state management, you know, you're building something, how would you make a decision and what would you choose?

 

Robin Heinze:

Um, I would probably look at where my data is coming from. If it's, am I loading it from an API? Am I... how, like, how often am I loading it? Is it something that I need to load every single page load? Like, is it maybe healthcare related? And I can't store data because of HIPAA, those are considerations. Or am I managing the ent- like my entire state, like, own on my own as a single app, and not, not integrating with an API. Those would all factor in. Uh, also just how, how big the app is, how much data there is. If it's a few screens, then sure, we can manage data on each screen using hooks. That's no problem. Is it going to be really large? Do I have to scale? What does my team know how, know how to use? Yeah, lots of factors.

 

Jamon Holmgren:

Absolutely. Tho- that's a great list. And you can also mix and match a little bit. So, if you chose MobX State... Or, actually you're, you're using MobX-state-tree in your current project.

 

Robin Heinze:

That's true.

 

Jamon Holmgren:

And you showed me a component where you actually use a hook, I think, to manage the state of that component.

 

Robin Heinze:

Yes. The, yes. Most of the time I keep most logic in MobX-state-tree. Um, but this was a case where there was a lot of logic, but it was all entirely related to how the component was rendering. So, it was view layer logic, essentially. And so, I had three or four different used state calls.

 

Jamon Holmgren:

What's an example of that? In, like the one you're talking about.

 

Robin Heinze:

So the, the component I was building basically had, uh, a grid of small buttons, and the ability to show more, or which would show the entire list of buttons, and then also show-

 

Jamon Holmgren:

Sort of like a tag cloud, right?

 

Robin Heinze:

Yeah, yeah, exactly. So you'd show more, and then it would display a less button. So you could show less and go back to a single line, basically. But the kinds of things I was keeping track of were, A, how many total buttons were in the list, and how many were visible at any given time? I'm trying to think, uh, what else. Basically, how many, so, because of the way the grid was laid out, I had to add some sort of placeholder views in order to get Flexbox to do its thing, and not like, expand the buttons to fill the whole row, when there were only two in a row of four. so I had to do some math, some, uh, modular math-

 

Jamon Holmgren:

Fun, fun, fun.

 

Robin Heinze:

And you can keep track of like, how many spacers to put in. That kind of thing. Um, but yeah, it was all using hooks. Used state.

 

Jamon Holmgren:

Yeah, that's cool. So you can just mix and match it, in, in that case. Harris, uh, same question to you. How would you kind of make a decision on what state management to use, and, uh, then what would you use?

 

Harris Robin Kalash:

My answer won't be as I guess, uh, responsible as Robin’s, I would use MobX just because it makes my life easier. (laughs) So, but, yeah. I mean, I've tried so many state management solutions and I, I think there hasn't been one that's, I haven't regretted as much as MobX, where, uh, in the sense of like, not, not, not regret it, but in the sense that like, as the application grew, sort of, I felt like, oh, this is becoming kind of a pain, or it's tedious. Maybe it's different in large teams, because I've typically worked with small teams, but maybe the next one I would want to try is either a new one. Like, I guess I would either do MobX, or a new one. But I wouldn't try anything other than that, I've tried already again, other than MobX.

 

Jamon Holmgren:

Yeah. That makes sense. And also what your team is used to. Although, we've actually a lot of success converting Redux people over to MobX-state-tree, that's, that hasn't seemed to be a major problem, mainly because MobX-state-tree makes MobX more like Redux. So it just kind of, there's a lot of familiar concepts, yeah. Yeah. And I would, I would echo that. And certainly from a business owner perspective, when I'm looking at it, Redux is an obvious choice because there are so many Redux savvy engineers out there, and there's so much like third party support and stuff. The MobX-state-tree is probably like, and MobX itself, are, they're definitely the solid runner-up in that category. And I would say probably 10% of, of React Native projects probably use, uh, React, uh, MobX-state-tree. I know when I'm giving those talks, I ask, and it's usually like 80% use Redux, 10% use MobX-state-tree, and 10% are like, everything else, including just using hooks and context.There's a lot of Unstated in there, too, but Unstated has some limitations. Uh, that's why they're kind of coming out with, with Unstated Next. But yeah, I, I, I think that's a great way to look at it.

 

Jamon Holmgren:

So at this point, I'd like to introduce a new section of the podcast. Uh, we are going to go into our, our fun part (laughs) and that is weird bugs. So weird bugs is, uh, it's a section where are we just talk about weird bugs that we've encountered ourselves, or we've heard other people talk about, or we've just noticed in the wild. Not everybody's going to have a weird bug every single time that we, that we do these episodes, but who's got a weird bug this, this time around.

 

Robin Heinze:

Uh, so, uh, yesterday, I think, or the day before, uh, one of our teammates pointed out that there was a recent PR to React Navigation, fixing a bug where, so a listener was added, uh, using Use Effect, but then was never removed and was in fact added again, one component unmounted.

 

Jamon Holmgren:

So they had, they were returning. So Use Effect, the way that this works is you give it a function which like sets things up, a lot of times listeners or whatever observers. And then you can return a function that will tear that down. It will remove those listeners, et cetera. This wasn't doing that, right? It was adding it again.

 

Robin Heinze:

Yes. So there's a, there's a hook, uh, from React Navigation called Use Window Dimensions, which basically returns to you the width and the height of your window.

 

Jamon Holmgren:

Right.

 

Robin Heinze:

And so it adds, it, it has, it uses Use Effect to add an event listener or using the React Native Dimensions API. And, but then, the Use Effect call was returning dimensions dot add event listener, again.

 

Robin Heinze:

So, that was not a great bug, uh, but the, this PR was changing it to remove event listener.

 

Jamon Holmgren:

So the, the more that your application would run in React Navigation, and there were, window dimensions changing to some degree, the more listeners you would pile up, and the more often, if a change happened, it would just run this function, the on change function over and over and over and over again. Uh, you know, maybe who knows how many times,

 

Robin Heinze:

Which is a bit of a memory leak.

 

Jamon Holmgren:

Exactly.

 

Robin Heinze:

Uh, yeah. So update React Navigation, if you're using it.

 

Jamon Holmgren:

Yes. Yeah. They did merge in this, uh, three days ago. I don't know what, what version it has made it into, if any yet. Uh, but yeah, definitely.

 

Robin Heinze:

It's just proof that like, even the authors of our favorite libraries are not immune to little things like that.

 

Jamon Holmgren:

Totally.

 

Robin Heinze:

Yeah. We're, we're all human.

 

Jamon Holmgren:

(laughs) Very cool. Well, thanks to everybody who's listening. Thanks to my company, Infinite Red, for making this episode possible. Very excited. This is the second episode since we relaunched the new React Native Radio. And of course, thanks Robin, thanks Harris, for being with me today. Hopefully Adhithi we'll be back next time, so we can get her perspective. And I'm also working on some really cool guests. So, stay tuned because the guests are going to be awesome. There's going to be some new people that have not been heard on this podcast before. And, uh, that's, that's going to be a lot of fun. So thanks everybody. We'll see you next time.