Too much state at the top? (beginner question)

(JW) #1

I’m learning React by creating a multi-tabbed app, which uses React Router 4. I want each tab to maintain its contents even when you switch away, similar to the iOS App Store.

Since the router removes a component when it’s not in the current route, I can’t store any state in my tab components, or it will get lost when you switch away. So, having taken Thinking in React to heart, I’ve pretty much moved all my state up to the top-level App component.

But as a result, my App component is way too complex. For example, each tab loads some data over the net. So for each tab, my App component has state fields for the data, the loading/loaded state of the data, its sort direction/order, its filters, etc. Plus it’s got event-handler functions to load, sort, filter, add, update, and delete data, which it passes down to the lower-level components within the tab.

Is this a common problem? How do I simplify things? I’ve avoided adding Redux because of articles like this, and since this seems like a pretty simple app. Any advice would be appreciated…let me know if this isn’t the appropriate forum.

(Joe Dodd) #2

It might help to see just how complex your App component is via your code. From what you’ve described, it doesn’t sound too complex to me. But others may have different opinions.

(JW) #3

I can’t really post it here, but it’s definitely starting to get bigger than any sensible class should be. I’m working on factoring out some things into separate classes.

But the main problem I run into is that the App component still needs to have access to all the state. So if I move code into a separate class, it needs to call back to the App component somehow to get/set the state. This seems ugly. If all my setState and this.state calls need to happen in App, it kind of limits what kind of logic I can move into other classes.

The other problem is that the App also needs access all the event-handler callbacks, to pass on to its child components. These seem a little easier to factor out, since I can put them in separate classes and just refer to them from App.

(Dantenovski) #4

I’m building my first practice Express/React app and I opted to use React-Redux (well Redux-Saga to be exact). It took some time to grasp the logic behind both redux and sags and it does add some boilerplate but in the end I very happy I have it. It makes managing state super easy. I think whether the app is small or large one will definitely benefit from it.

(Evan G) #5

I am in a similar situation, and I believe this is a common issue. I too am looking for design patterns to deal with this, without learning any 3rd party extensions like Redux etc.

(JW) #6

I ended up using MobX, which has solved those problems. I’ve come to the conclusion that if you want to do anything beyond a very simple app with React, you need to use a separate state-handling framework.

With MobX, I’ve pretty much removed all uses of React’s state features. Instead, my state is stored in objects that are tracked by MobX. Then individual React components can monitor these objects, pass them in as properties, and re-render themselves when they change. This means I don’t have to pass everything down from the top-level component. It also has the advantage of keeping the application logic completely separate from React, which is now just used as the view layer.

I also tried Redux, which has its advantages. But it requires a lot of boilerplate, and involves a pretty different way of thinking about state, which I’m afraid would confuse my team. It also seems to require something like redux-saga to do pretty basic tasks, and this requires some unusual features of JavaScript which I wasn’t quite ready to dive into.

I also dropped React-Router and added router5, using something like this approach. This puts the routing on the application-logic side of the app, instead of being directly connected to React’s view layer. It seems to be working so far, although it’s still early days, and I haven’t seen a lot of other people doing things this way.