Hacker News new | past | comments | ask | show | jobs | submit login

A (presumably controversial) way to use React is to use only props never state, manage state in your own variables (possibly in a separate "controller" class) and call forceUpdate() when you have changed those variables such that the render would change.

This gives me flexibility to structure the code how I want. You can have the separate "controller" classes deal with operations (like API requests) and the "react class" mostly deals with display - it delegates actions to the controller and retrieves data from the controller. This can promote code reuse, notably certain components can share the controller class (not instance) when you have similar logic.

As a more general principle, I like react just fine as a way to express the DOM in a functional way and for its magic of figuring out just what parts of the actual DOM must be updated; but I don't really care about how React wants me to write code in other aspects, like where and how I should manage my data.




Actually, using props instead of state is a pretty common thing to do - it's how redux integrates with React [1]

[1] https://redux.js.org/docs/basics/UsageWithReact.html


Hi, I'm a Redux maintainer. One of the most frequent areas of confusion around Redux is whether you can / should put any data into React component state when you're using Redux. The answer is "yes, you can, and it's up to you what state lives where". The Redux FAQ entry at https://redux.js.org/docs/faq/OrganizingState.html#organizin... has some rules of thumb to help you decide what state should actually live in Redux.

I've certainly seen a number of people in the community who insist that you _must_ keep everything in Redux, and that you should probably only use functional components along with that. I can understand why people might want to do that, as it means there's more state in the Redux store for traceability, UI output becomes highly predictable, etc. However, I would say that approach is too dogmatic and over-opinionated. It's a valid choice if you want to go there, but not something that should be enforced across the ecosystem or taught to learners. Class components, functional components, Redux store state, and React component state are all tools with specific use cases, and throwing any of them away is unnecessarily limiting your toolbox.

(Might not have been exactly what you were asking, but given how frequently this topic comes up, I wanted to put that clarification out there.)


What i like to do is to write every component as a stateless component. This way you can write a wrapper component that handles local state, lifecycle methods etc and just pass the needed functions and variables to the dumb component or you can switch to redux. The component doesn't care it just needs to have the state altering functions as parameters and the updated state. The problem i see is when new developers start writing a huge class that is coupled with the state handling and calling this all over the place.


I use withState from recompose heavily for this reason.


That’s what I do. Even if you’ll likely never use the stateless component directly in an app, it makes automated testing and things like Storybook much simpler.


Yeah, I'd definitely argue that using Redux should be the last resort. When only a single component ever needs to care about data, using component lifecycle is much more self-contained


... but also a very bad idea in practice, as most devs eventually find out. Using the Redux store in lieu of state spreads code that could otherwise be self-contained all over your codebase. It's a good way to make a huge mess and write some very brittle code.


I would refer to acemarke's comment above. It's not gospel to have to use redux for all your state. I prefer to separate my state into tiers conceptually.

Think of the classic case showcase of redux being used with immutable structures to implement a page-wide undo easily. There's a certain amount of state that could be burried deep in components that doesn't need to be in the global redux store.

Sure, your undo might not now be an exact representation of the historical state of the page, but the state that counts is still re-created, and that's the state that you can decide to put into redux.


I’ve managed a huge React app with Redux and never came across this - I can’t imagine how your case would come up. Even though we use a single state object, the concerns of a single piece of state tend to be contained in its reducer and component only.


Do you maintain a 1:1 relationship between reduced state and components? I'm curious because your word choice seems to imply you do and I'm wondering how popular that is if so.


I'll be honest - I'm having trouble parsing what having a '1:1 relationship between reduced state and components' actually means. The most common "state" in our application is the result of a GET request (for example, you need some data from the server), and an accompanying loading/loaded/error state.

Most (presentational) components will load its needed data from a container component (through connect(), or other higher order components we developed). So for example, a given `user` object, could have its data in a chat component, or an analytics view, or a settings profile. The reducers aren't generally concerned with how the data is used, just that its available to anyone who asks.

As far as localized state goes (like a form), we took a page from reduxForm (and we use reduxForm) - if there were times we needed to use setState a lot (for example, we had a query builder and chart components), we built a higher order component (like connect), where you would pass the props you need, and that component would figure out how to query it and make it available in the redux state. Again this meant you could create a "query object" from one component, that was theoretically available to any other component (as part of the Redux tree), if they asked.

All in all, I never considered any sort of 1:1 relationship between state and components. I had state, and the components decided what state they needed and rendered themselves appropriately. This was a fairly complex SPA that had real time chat, analytics and CRM-like features, there were 100s of components.

Our codebase was far more robust from the Angular version we had rewritten it from a year ago (a component crashing didn't bring down the whole app), and the concerns for every component tended to be self-discoverable (we were able to hire interns to start hacking on it within 2-3 days, after they wrapped their head around redux). I'll admit it took me sometime to understand the benefits of Redux, and there was a lot of ugly boilerplate until we started using higher order components, however "brittle" and "messy" is the last words I'd use to describe the codebase.


From a flux/reflux perspective I'd 1-1 relationship to mean that every component had a matching store, but since Redux has a single store not sure what pattern would match.


I don't think he's implying that. A good way to think about it is mapping reducers -> features.

Reducers are composable, so you can actually end up with pretty clean code in large codebases


I find that hard to believe. Coupling state with components is exactly what makes React brittle imo.


It sounds like you don't have experience with redux and how it is used, which makes me surprised that you have such a strong opinion about it.

Redux makes available state that is required globally, like the contents of your todo list or other properties that must persist as you navigate a web app. Components will store their own state for their specific requirements.

I suggest reading up on redux use cases to find out more before dismissing it entirely.


It's not controversial at all.

What is controversial is the (incorrect) notion that developers shouldn't use state. There are some perfect use cases for state and people somehow got the idea that they shouldn't use it (as opposed to not using it as the first tool, necessarily, if props can be used).


This was exactly the motivation behind a project I wrote called react-redux-controller [1]. It has made for great separation of concerns between state management (Redux), display logic (React), and implementation of processes (the controller functions). It's completely possible to segment portions of the app such that slices of those three aspects are colocated and then composed as needed.

I don't necessarily recommend using this project specifically, as I don't devote any time to maintaining it. There's a whole next-generation of how I think it should work that I haven't gotten around to persuing. But I mention it to back the overall approach. It makes UI refactors extremely easy, as components are generally not responsible for any dependencies of their descendant subtree, with the exception of some parent-child interactions.

I haven't tried it, but I think Freactal [2] also seems to allow for this sort of separation of concerns.

[1] https://github.com/artsy/react-redux-controller

[2] https://github.com/FormidableLabs/freactal


You can also ignore React's built-in 'state' object and just store stuff directly in variables using MobX, which will force update components for you.

That said, it is best used as you describe it: a store that holds all the application state and manages API requests, and then any time it updates, any components observing this store will be forceUpdated


I agree with your 'stateless' approach for many use cases that are otherwise 'muddied' by unnecessary component state.

However, instead of calling forceUpdate(), I was under the impression that componentWillReceiveProps(props) was more efficient?

Perhaps I'm wrong on that one, though... Just that forceUpdate() is an approach that is officially encouraged against.[0]

[0] - https://reactjs.org/docs/react-component.html#forceupdate


The question I ask when deciding between component state (via setState) or application state (via hoisting / redux / mobx) is simply whether the state is relevant to the application as a whole.

One example is the text I’m currently typing - that would only be relevant at a component level, maybe including an adjoining word counter. Once I hit reply, though, it becomes part of the application state.

An exception would be if I was continuously storing what was typed for offline use - in that case it’s always application state.


Then you might like Undux - that's exactly how it works.

https://github.com/bcherny/undux


You are describing redux.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: