My first project with React was a mess, mostly because of Redux. Not because it's bad, but because the lead dev was adamant about using something Flux like. First we had Flummox, than he rewrote everything in a week with Redux, that was 2 years ago, before Redux had sane async helpers.
In my current project (where I'm the lead, haha) I'm trying to got state/props all the way.
I think for most apps it's more than enough AND it's easier to get started for new devs.
React is really easy. I mean coming from Ember and ExtJS, its API is a walk in the park and you can get really far without extra state management.
One thing that is important for this approach, minimize nesting.
You don't want to pass down everything from the app, to the screen, to the list, to the item. etc.
Instead of doing:
<List items={items} />
do it like that
<List>
{items.map(i => <Item item={i}/>)}
</List>
No nesting of screens (top-level components), no (hidden) nesting of components. This may seem kinda strange, because the first example has no dependency to the Item component, but it gives the component that uses the List direct access, which simplifies props-passing immensely.
This doesn't work for all apps, but it's a good starting point.
I ended up with 2 folders, screens and components, that are both simply flat lists of component files.
Also, when you do use Redux, as in your nesting example don't pass props through components that don't have any need for them except they propagate the prop to someone else. It's absolutely fine to connect() a component deeper in the hierarchy. Passing everything down is an anti-pattern with Redux, separation of concerns still applies and the props of a component defines the API, don't clutter that API with unrelated things.
Components only receiving props that they themselves need has kept things clean in our massive codebase, and allows you to effortlessly move things about and easily re-use components wherever it makes sense.
I partially blame every tutorial and contrived example of how you should use Redux.
When first starting with React & Redux I spent some time thinking of where and how I should use Redux.
Being that I was new to both, I didn't have any ingrained best practices, and it was hard to find any best practices around when to use redux.
Every example seemed to use it for everything, which seemed insane to me in a real web app. I could see that the size and clutter would grow terribly, and for no obvious benefit.
Your example above is similar to how many component libraries work (where you need to give the user flexibility).
In a dashboard app, I'll make good use of Redux because there are often sets of data you revisit in different ways.
In a more directory-like site I've recently built I use it to keep track of the logged in user information and high level information that dictates your experience (like user location), but nothing else.
I've been doing React for a while now and I've ended up with the same structure: 2 main folders.
One of them in the base components, which are in folders grouped by their corresponding REST service endpoint (so if you have 'Foo' and 'Bar' db tables, and API's, then I have 'Foo' and 'Bar' folders inside my 'components' folder.
The other folder is my views. It's more of the integration layer for all of my components. Since views typically correspond to a page route, that's where most of my react-router stuff is. It also is where I call the react-redux 'connect' HOC, to get data that is fed down into the components.
So far it's working pretty well for me. I think it works great for a medium-size type of app.
In this kind of setup, I'm wondering how you handle events that happen outside of the component?
Let's say you have a background function, created with setTimeInterval, which after some time update an item. With Redux, you could dispatch an action UPDATE_ITEM, which would modify the items, and in turn update the connected component.
However, without Redux how is your component going to know about this item update and update the list? Do you use some kind of event listener/dispatcher?
That approach may minimize props passing, but it also is going to cut down on chances to use `shouldComponentUpdate` to avoid unnecessary re-renders and improve performance. Depending on your app, that might not be an issue, but it's something to be aware of.
I'd rather use Redux without React than React without Redux. Sure there's some boilerplate but we use typescript so the redux boilerplate seems trivial in comparison.
Redux keeps your app _simple_. That's not the same as easy. It means that you can reason about your app as it grows and new features are added. When you run into problems like: this page is taking too long to load because we do calculations x, y and z on the server to push the data to the app. But z takes forever to compute and makes the initial page load painful. With Redux, you can move z to an async endpoint and just load x and y on page load (put the component that needs z in a loading state). Then, fire an ajax request when the component mounts to get z. When that call returns, it updates your store and the component that needs z transitions from loading to loaded.
I took me a couple of hours to do the above in a Redux app and decrease the page load from 2 seconds to 300ms. And it didn't add complexity to the app that would make it difficult to maintain. I don't even want to think how long that refactor would take if the state had been managed with React.
And ... don't even get me started on how easy -- and fast -- it is to test a Redux app. Zero side-effects means zero setup and teardown between specs.
The rush to use Redux for every React project is one of the most annoying parts of the React community; using a tool just to use it, before understanding if you need it or not. This article summarizes a lot of good points.
Agreed. Until recently, my team was responsible for most of the official IBM Watson service demos, and we standardized on React for those and built up a nice library of react components[1]. None of them used Redux, though, because in general it just wasn't needed.
When we handed off responsibility of these demos to the individual service teams, we wrote up guidelines that specifically recommended React but not Redux - with the logic that if the demo is getting to a point where Redux is providing value, then it's probably too complex for a demo.
Our new project is a more involved web app that includes lots of state, shared across many different components, and we're making great use of Redux there.
This summarizes everything about the JavaScript ecosystem, so it shouldn't really surprise React users that there is no logic behind the community's behavior.
People have finally succeeded in making JavaScript an important development platform by sheer force of will, insisting that JavaScript must become important in order to justify their adoption of the fad. Before this critical mass was attained, there was no real reason to use JS whenever the option was available, and virtually everyone who adopted Node.js and friends was doing it "just to [do] it", in service to the fad kicked off by Google's promotion of Chrome/V8.
Consider that prior to V8, JavaScript was so disliked that the only way to get someone to read a book about it was to name it "JavaScript: The Good Parts". The coder would be surprised to hear that anyone thought JavaScript had any good parts, and would want to figure out what they were, so that his/her days spent in client-side hell would go just a little smoother.
Then Google released Chrome with V8, some people thought this meant JavaScript was cool now, and it's snowballed from there.
As usual, this is an excellent article by Robin. Well-written, and full of great information.
It's worth noting that both the React and Redux teams (including Dan Abramov and myself) agree that you should focus on learning React first, and _then_ learn Redux. That way there's fewer new concepts and terms to learn at once, and once you understand React, you'll have a better appreciation for what kinds of problems Redux can help solve. That's not to say you _can't_ learn them both at once, just that it's the suggested approach that will work best for most people.
I wish React would come with a standard way to handle Ajax (or a convention or semi-standard library would emerge). (Edit: "comes along" in the sense that immutability-helpers, redux and create-react-app come along with react. I'm not proposing to add anything to the react module. I'm not the world's best expert on react, but before downvoting can you please assume I know a little bit of what I'm talking about?)
Something that:
- Can fetch JSON according to criteria from an API
- Caches stuff locally (just in memory, or in local storage) in case of duplicate calls
- Deals with multiple concurrent calls, and merge them (e.g. fetching 1 and then 2,3,4 before 1 finishes -> either cancel 1, or wait until it finishes, and then fetch only the last requested item.
- And all the stuff I can't think about right now, like cancellation and timeouts
Plug your pure component into one of these, tell it about your API, and you're done. It's really error prone to write these containers yourself. And I think Redux doesn't really help much with Ajax.
React _is_ only a view library. It shouldn't have any thing to do with things like Ajax - that's part of what makes it simple to work with l. It does one thing and does it well.
It doesn't even seem to be the responsibility of Redux, which more so is consider with prescribing _how_ data and actions flow through your system, not how exactly those calls touch the outside world.
I don't like employing the phrase "separation of concerns" that often / without serious thought, but this is seems to be a valid use case for it. Presentation components shouldn't care about how fetches data, they should ideally just be a function of their props. Even container components should only care about what data they are accessing, not how it comes to be in the data store.
What you're asking for could just be a plain JS library - when you ask for certain routes in your app, fetch some data. When it comes in, handle all those edge cases you describe. Update the data store. When that happens, we're finally back in Redux land. It doesn't care about how you fetch your data, all it cares about is _that_ you touched it at all.
But React isn't a framework. It's only a view library. So by definition, it shouldn't care less about Ajax. Similarly, Redux is only a state-management container. It also shouldn't care about Ajax. What you're probably looking for is redux-saga[0]; it provides the tools to let you easily write all the fancy functionality you're talking about.
Relay is what is supposed to be doing this for React. I highly recommend Relay if you have a graphql api to talk to. I had to fight it initially (the docs are not good enough, although better than before, and I need to contribute what I learned) but once I got going it's made what took an incredible amount of time in Mobx, Redux, or Flummox much easier.
I have a network-state in every application, usually as a set of "NetworkRequests", which are data-object that describe a request. Just like I sync the UI-state to the browser using React, I sync the network-state to the network by
a) using a custom NetworkManager, that takes a set of requests and syncs it with currently running requests.
b) using react itself. In a simple project I created a ReactComponent for every network-request. The render() is just an invisible div, the actual requests get started and stopped in componentDidMount() and other life-cycle hooks.
This approach works everywhere, it is serialisable and easy to think about.
I tend to write the redux-part ("controller") of my applications myself, it's seldomly more than 100 lines and more adaptable to my needs.
And I never use immutable.js, it's really unnecessary and slows down development-speed (via it's weird api) and runtime-performance.
Shouldn't the browser be doing the caching? Now that they even have the Fetch API, which can return actual JSON objects, they could even cache them pre-parsed.
Shameless self-plug. I developed a design pattern I call "vacancy observers" that solves a subset of the Ajax problem. Basically, fetching data for display; AKA the "R" in CRUD. My POC implementation is on Github.
I don't see the need for either Redux or MobX. React is the V in MVC. Use an MVC framework with React, and everything get simple, easy and productive. There are MVC frameworks that work well with React. Redux is unnecessary complexity and the need for it came about because of ReactRouter. If you use an MVC router you can avoid a whole bunch of complexity.
BTW, using MVC doesn't imply two-way data binding.
Well, there are many reasons to use React (the large ecosystem means you can find libraries and tutorials easily, for example) but yes, the license is a deal breaker for many, especially larger companies with legal teams who actually understand the ramifications.
Not sure what specifically your aversion is to the React license, but a similar project - Preact - uses an MIT license: https://github.com/developit/preact
NOTE: not affiliated with Preact (I live in the caves of the backend).
My understanding of this licence is "we're making open-source software, play by the rules and don't sue us or we might find other ways to put you in trouble"
[+] [-] k__|8 years ago|reply
In my current project (where I'm the lead, haha) I'm trying to got state/props all the way.
I think for most apps it's more than enough AND it's easier to get started for new devs.
React is really easy. I mean coming from Ember and ExtJS, its API is a walk in the park and you can get really far without extra state management.
One thing that is important for this approach, minimize nesting.
You don't want to pass down everything from the app, to the screen, to the list, to the item. etc.
Instead of doing:
do it like that No nesting of screens (top-level components), no (hidden) nesting of components. This may seem kinda strange, because the first example has no dependency to the Item component, but it gives the component that uses the List direct access, which simplifies props-passing immensely.This doesn't work for all apps, but it's a good starting point.
I ended up with 2 folders, screens and components, that are both simply flat lists of component files.
[+] [-] Androider|8 years ago|reply
Components only receiving props that they themselves need has kept things clean in our massive codebase, and allows you to effortlessly move things about and easily re-use components wherever it makes sense.
[+] [-] lilbobbytables|8 years ago|reply
Being that I was new to both, I didn't have any ingrained best practices, and it was hard to find any best practices around when to use redux.
Every example seemed to use it for everything, which seemed insane to me in a real web app. I could see that the size and clutter would grow terribly, and for no obvious benefit.
Your example above is similar to how many component libraries work (where you need to give the user flexibility).
In a dashboard app, I'll make good use of Redux because there are often sets of data you revisit in different ways.
In a more directory-like site I've recently built I use it to keep track of the logged in user information and high level information that dictates your experience (like user location), but nothing else.
[+] [-] Y7ZCQtNo39|8 years ago|reply
One of them in the base components, which are in folders grouped by their corresponding REST service endpoint (so if you have 'Foo' and 'Bar' db tables, and API's, then I have 'Foo' and 'Bar' folders inside my 'components' folder.
The other folder is my views. It's more of the integration layer for all of my components. Since views typically correspond to a page route, that's where most of my react-router stuff is. It also is where I call the react-redux 'connect' HOC, to get data that is fed down into the components.
So far it's working pretty well for me. I think it works great for a medium-size type of app.
[+] [-] laurent123456|8 years ago|reply
Let's say you have a background function, created with setTimeInterval, which after some time update an item. With Redux, you could dispatch an action UPDATE_ITEM, which would modify the items, and in turn update the connected component.
However, without Redux how is your component going to know about this item update and update the list? Do you use some kind of event listener/dispatcher?
[+] [-] acemarke|8 years ago|reply
[+] [-] rednotebook|8 years ago|reply
getItem = i => <Item item={i}/>
...
<List> {items.map(getItem)} </List>
[+] [-] Kiro|8 years ago|reply
[+] [-] spinlock|8 years ago|reply
Redux keeps your app _simple_. That's not the same as easy. It means that you can reason about your app as it grows and new features are added. When you run into problems like: this page is taking too long to load because we do calculations x, y and z on the server to push the data to the app. But z takes forever to compute and makes the initial page load painful. With Redux, you can move z to an async endpoint and just load x and y on page load (put the component that needs z in a loading state). Then, fire an ajax request when the component mounts to get z. When that call returns, it updates your store and the component that needs z transitions from loading to loaded.
I took me a couple of hours to do the above in a Redux app and decrease the page load from 2 seconds to 300ms. And it didn't add complexity to the app that would make it difficult to maintain. I don't even want to think how long that refactor would take if the state had been managed with React.
And ... don't even get me started on how easy -- and fast -- it is to test a Redux app. Zero side-effects means zero setup and teardown between specs.
[+] [-] sghiassy|8 years ago|reply
[+] [-] nfriedly|8 years ago|reply
When we handed off responsibility of these demos to the individual service teams, we wrote up guidelines that specifically recommended React but not Redux - with the logic that if the demo is getting to a point where Redux is providing value, then it's probably too complex for a demo.
Our new project is a more involved web app that includes lots of state, shared across many different components, and we're making great use of Redux there.
[1]: https://watson-developer-cloud.github.io/react-components/
[+] [-] _greim_|8 years ago|reply
I like React's ethos of avoiding complexity until you need it, but these smug attitudes are starting to get really tiresome.
[+] [-] cookiecaper|8 years ago|reply
People have finally succeeded in making JavaScript an important development platform by sheer force of will, insisting that JavaScript must become important in order to justify their adoption of the fad. Before this critical mass was attained, there was no real reason to use JS whenever the option was available, and virtually everyone who adopted Node.js and friends was doing it "just to [do] it", in service to the fad kicked off by Google's promotion of Chrome/V8.
Consider that prior to V8, JavaScript was so disliked that the only way to get someone to read a book about it was to name it "JavaScript: The Good Parts". The coder would be surprised to hear that anyone thought JavaScript had any good parts, and would want to figure out what they were, so that his/her days spent in client-side hell would go just a little smoother.
Then Google released Chrome with V8, some people thought this meant JavaScript was cool now, and it's snowballed from there.
[+] [-] acemarke|8 years ago|reply
It's worth noting that both the React and Redux teams (including Dan Abramov and myself) agree that you should focus on learning React first, and _then_ learn Redux. That way there's fewer new concepts and terms to learn at once, and once you understand React, you'll have a better appreciation for what kinds of problems Redux can help solve. That's not to say you _can't_ learn them both at once, just that it's the suggested approach that will work best for most people.
[+] [-] hippich|8 years ago|reply
If you need to use state to set new state, use functional callback instead - https://facebook.github.io/react/docs/react-component.html#s...
[+] [-] tchaffee|8 years ago|reply
[+] [-] captainmuon|8 years ago|reply
Something that:
- Can fetch JSON according to criteria from an API
- Caches stuff locally (just in memory, or in local storage) in case of duplicate calls
- Deals with multiple concurrent calls, and merge them (e.g. fetching 1 and then 2,3,4 before 1 finishes -> either cancel 1, or wait until it finishes, and then fetch only the last requested item.
- And all the stuff I can't think about right now, like cancellation and timeouts
Plug your pure component into one of these, tell it about your API, and you're done. It's really error prone to write these containers yourself. And I think Redux doesn't really help much with Ajax.
[+] [-] thatswrong0|8 years ago|reply
I don't like employing the phrase "separation of concerns" that often / without serious thought, but this is seems to be a valid use case for it. Presentation components shouldn't care about how fetches data, they should ideally just be a function of their props. Even container components should only care about what data they are accessing, not how it comes to be in the data store.
What you're asking for could just be a plain JS library - when you ask for certain routes in your app, fetch some data. When it comes in, handle all those edge cases you describe. Update the data store. When that happens, we're finally back in Redux land. It doesn't care about how you fetch your data, all it cares about is _that_ you touched it at all.
[+] [-] peller|8 years ago|reply
[0] https://redux-saga.js.org/
[+] [-] 0xCMP|8 years ago|reply
[+] [-] cel1ne|8 years ago|reply
a) using a custom NetworkManager, that takes a set of requests and syncs it with currently running requests.
b) using react itself. In a simple project I created a ReactComponent for every network-request. The render() is just an invisible div, the actual requests get started and stopped in componentDidMount() and other life-cycle hooks.
This approach works everywhere, it is serialisable and easy to think about.
I tend to write the redux-part ("controller") of my applications myself, it's seldomly more than 100 lines and more adaptable to my needs.
And I never use immutable.js, it's really unnecessary and slows down development-speed (via it's weird api) and runtime-performance.
[+] [-] 18nleung|8 years ago|reply
[+] [-] icebraining|8 years ago|reply
[+] [-] fokinsean|8 years ago|reply
[+] [-] _greim_|8 years ago|reply
https://github.com/greim/motel
[+] [-] noncoml|8 years ago|reply
My advice to anyone reading this forum is give MobX a try before deciding to commit to Redux.
[+] [-] ng12|8 years ago|reply
[+] [-] interlocutor|8 years ago|reply
BTW, using MVC doesn't imply two-way data binding.
[+] [-] unknown|8 years ago|reply
[deleted]
[+] [-] bernadus_edwin|8 years ago|reply
[+] [-] RussianCow|8 years ago|reply
[+] [-] TotallyHuman|8 years ago|reply
[+] [-] enraged_camel|8 years ago|reply
[+] [-] ttrunck|8 years ago|reply
This reopenned the discussion about React licensing (https://github.com/facebook/react/issues/10191) so maybe this will change soon.
[+] [-] joshmarlow|8 years ago|reply
NOTE: not affiliated with Preact (I live in the caves of the backend).
[+] [-] a13n|8 years ago|reply
[+] [-] unknown|8 years ago|reply
[deleted]
[+] [-] pbasista|8 years ago|reply
[+] [-] t_fatus|8 years ago|reply
[+] [-] meesterdude|8 years ago|reply