12 ms·
Build Yourself a Redux
- dgregd 9y agoI've seen and understand Redux TO DO examples. However I develop enterprise CRM app. In db there are 200k client records, 500k sales calls records. It is implemented as a standard Ruby on Rails / Postgresql web app. It works quite well. It is also pretty straightforward to implement a such app in a Java/PHP MVC framework. Let's say I would like to implement UI using React/Redux. How should I start? For example the app has calendar month view, for each day there are 20 sales calls. So the month view has 400 sales calls and clients data displayed (date, time, client name, target group). Do I have to put 400 sales calls and 400 clients data to a Redux store to display the calendar month view? What about client data search results and pagination? In just few clicks a user can display hundreds of clients records (thousands in case of results map view). Do they belong to a Redux store? If a user modifies one sales call record, how it is persisted in central DB? What about edge cases where some uniqueness conditions have to be checked on central DB level? Rails covers all things needed to implement my medium CRM app. When I read Redux TO DO tutorials I have a filling that they cover just 10% of what is needed to implement a full CRM app. Could you please direct me to Redux examples / tutorials how to implement a full enterprise database app (SugarCRM scale). PS. to down voters, please write a few words what is wrong with my questions so I can learn what is appropriate to post on HN
- benjaminjt 9y agoNeither React nor Redux really prescribe an architecture so building an app with these libraries requires some extra thought over just using a framework. An approach I often see is to use Redux as a single state container in a monolithic flux architecture (which seems to be referred to as "Redux") but this has advantages and disadvantages, and is certainly not the only way to use these libraries. If you're going to go down the flux path, I would suggest you map out the minimal state which can completely represent your user interface (store structure), then list all the state mutations (actions) which you expect to affect this state. That might help you build up clear picture for how to develop your CRM app. It's good to keep in mind that at the end of the day React and Redux are just tools, and it is up to you how to use them.
- WA 9y agoI upvoted you, because I think this is a total legitimate question and I don't get the downvotes either. This was exactly the question I had, when I read about Redux at first. After all, the Redux docs say that "don't worry about performance, unless you have tens of thousands of objects". So, the answer I can give you as someone, who starts to get Redux, but I'm nowhere near being an advanced user: In your Rails app, you wouldn't render all 500k sales records on the same page as well. You'd probably have some sort of pagination. With Redux, it's the same. You don't have 500K objects in store, but only the 30 sales calls you're currently displaying. Redux contains the state of the current view and if you want to load more data, you'd have some async methods to fetch data from the DB or an API and refresh the Redux store. Your Redux store isn't: [sales_call01, sales_call02, ..., sales_call500000] It's more like: { viewCalls: [sales_call452, sales_call453, sales_call454] } But still: Many tutorials are way too simple and gloss over the details. They make it sound as if Redux is the architecture and the store holds all data for the entire app. What I haven't figured out: Say, you're using Redux on the server and need to update all 500,000 sales calls. With Redux, you'd have to write a reducer that modifies the state tree. But if 500,000 sales calls don't fit into memory, how do you do it?
- 8note 9y agoit doesn't sound like redux is the right tool for the job. You're looking for a stream/file. You could still have a redux store, but it's role would be to manage the stream(process updates, keep track of errors, kill the stream if there are too many errors) rather than store the data for the job.
- acemarke 9y agoMy initial answer to that is that none of those questions are specific to React or Redux, but rather are common to _any_ Single Page Application, whether it be written in React+Redux, Angular 2, Angular 1, Ember, Backbone, or good ol' VanillaJS/jQuery. More specifically: yes, you would typically make AJAX calls on app startup to load some subset of records from the server, and continue to make more AJAX calls to request more records as needed (like when the user hits the "Next Page" button). Records requested from the server would indeed be cached client-side in the Redux store. When the user modifies an entry and hits "Save", you'd make another AJAX call to persist the updated values to the backend. Again, none of that is actually Redux-specific - it's just general workflow for an SPA. Some resources that may help. As mentioned elsewhere in the thread, I have a list of React/Redux tutorials and articles [0]. The "Redux Tutorials#Project-Based Tutorials" section [1] specifically lists tutorials that try to build something (preferably bigger than a TodoMVC app), rather than just explain the basics. In particular, the series "Building a Simple CRUD App with React and Redux" [2] is an excellent 8-part walkthrough that covers many key real-world concepts. I'll also put in a plug for my own "Practical Redux" tutorial series [3], which demonstrates some specific useful Redux techniques. Finally, you might want to glance at the "Redux Architecture and Best Practices" page [4] in my list for more articles on real-world approaches and concepts. [0] https://github.com/markerikson/react-redux-links https://github.com/markerikson/react-redux-links [1] https://github.com/markerikson/react-redux-links/blob/master/redux-tutorials.md#project-based-tutorials https://github.com/markerikson/react-redux-links/blob/master... [2] http://www.thegreatcodeadventure.com/building-a-simple-crud-app-with-react-redux-part-1/ http://www.thegreatcodeadventure.com/building-a-simple-crud-... [3] http://blog.isquaredsoftware.com/2016/11/practical-redux-part-3-project-planning-and-setup/ http://blog.isquaredsoftware.com/2016/11/practical-redux-par... [4] https://github.com/markerikson/react-redux-links/blob/master/redux-architecture.md https://github.com/markerikson/react-redux-links/blob/master...
- acemarke 9y agoThis is a great article! As I commented on the post itself when it was published, I keep a big list of links to high-quality tutorials and articles on React, Redux, and related topics, at [0]. That includes a section of "Redux implementation walkthroughs" at [1]. This is probably the best article of that type that I've seen. It not only covers the core of Redux, but also builds miniature versions of Redux middleware and the React-Redux `connect` function. I already added it to my list, and definitely recommend it. Readers may also be interested in my Redux addons catalog at [2], which includes links to hundreds of Redux middleware, utilities, and other useful libraries. That includes multiple ways to batch dispatching of actions. [0] https://github.com/markerikson/react-redux-links/blob/master/redux-tutorials.md#redux-implementation-walkthroughs https://github.com/markerikson/react-redux-links/blob/master... [1] https://github.com/markerikson/react-redux-links https://github.com/markerikson/react-redux-links [2] https://github.com/markerikson/redux-ecosystem-links https://github.com/markerikson/redux-ecosystem-links
- jdeal 9y agoThanks again, Mark!
- lalwanivikas 9y agoI am probably going to get downvoted to hell for this negative comment, but please stop doing this. I am really tired of seeing your "big list of links" everywhere I go[0][1]. If I click on anything even mildly related to React, Redux etc., on Reddit, HN etc. I always find the same thing. https://www.google.com/search?q="I+keep+a+big+list+of+links"+site:news.ycombinator.com https://www.google.com/search?q="I+keep+a+big+list+of+links"... https://www.google.com/search?q="I+keep+a+big+list+of+links"+site:reddit.com https://www.google.com/search?q="I+keep+a+big+list+of+links"...
- acemarke 9y agoYeah, I paste the link in a lot of places, because people keep asking the same questions, and the vast majority of people who see my list find it helpful :) It's really a case of XKCD's "Today's 10,000" ( https://xkcd.com/1053/ https://xkcd.com/1053/ ). There's always some people who find out about something for the first time, and I'm trying to help those people. FWIW, I do try to include those links as part of a larger comment relevant to the article or discussion at hand.
- neebz 9y agoShameless Plug: I gave a talk last year explaining similar concepts https://github.com/neebz/react-redux-presentation https://github.com/neebz/react-redux-presentation
- rasmi 9y agoIf anyone is interested in learning this content through an in-depth video tutorial, I highly recommend Dan Abramov's two-hour "Getting Started with Redux" [1] and the excellent follow-up "Building React Applications with Idiomatic Redux" [2]. This is a great article, but learning Redux more thoroughly directly from the creator himself may be of interest to some! [1] https://egghead.io/courses/getting-started-with-redux https://egghead.io/courses/getting-started-with-redux [2] https://egghead.io/courses/building-react-applications-with-idiomatic-redux https://egghead.io/courses/building-react-applications-with-...
- naragon 9y agoI came here to point out the Redux course by Dan Abramov on Egghead.io as well. I believe it's free. It's amazing how easy Dan makes it seem. It was a light bulb moment for me and finally made me understand the importance of immutability behind the React philosophy.
- johnfn 9y agoWould you mind expanding on that?
- acemarke 9y agoReact's default behavior is that when a component re-renders, _everything_ underneath it in the component tree re-renders as well. If you want a component (and its descendants) to skip re-rendering, you can implement the `shouldComponentUpdate` method. You can put any logic you want into `sCU`, but the most common implementation is to compare the contents of `this.props` and `nextProps` to see if anything actually meaningfully changed. You _can_ do a "deep equality" comparison that recurses through every nested field in both `this.props` and `nextProps`, but that's relatively expensive. The alternative is "shallow equality", which uses pointer/reference equality checks for each field in both objects. However, in order for that to be useful, you need to manage your data in an immutable fashion so that each update results in a new object/array reference, rather than directly modifying the existing objects. So, you don't _have_ to manage data immutably in React, but doing so enables performance optimizations, and also goes along with React's functional programming influences.
- floatboth 9y ago"Redux is a simple library" woah woah stop right there. How is this: const handlers = { [CREATE_NOTE]: (state, action) => { ... }, // ... a thousand more of this } simple? This looks horrible. Every time you want to work on code that modifies data, you have to switch to the one file where you keep all the data-modifying functions? Seriously?! Freezer https://github.com/arqex/freezer https://github.com/arqex/freezer is a much, much better experience. You just shove immutable objects down the component tree, and they just come with methods that modify "them" (by actually changing the data tree). It has an event system as well for when you actually want to centralize actions. Works great with Polymer, by the way!
- acemarke 9y agoYou're complaining about a couple different things. That particular reducer example is a bit terse, and could be made more readable. That said, yes, Redux (as a Flux Architecture derivative) does ask you to separate all your "write logic" from the rest of the application. This is explicitly part of the design. You may want to read Dan Abramov's article "You Might Not Need Redux", where he discusses the tradeoffs that Redux asks you to make, and the benefits you get as a result: https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367 https://medium.com/@dan_abramov/you-might-not-need-redux-be4... . I'm also working on a blog post that will discuss the actual technical limitations Redux requires of you, vs how you are _intended_ to use Redux, vs how it's _possible_ to use Redux. The goal is to clarify where the various common aspects of Redux usage come from and why. I'm hoping to finish the post over the weekend and publish it early next week. If anyone's interested, keep an eye on my blog at http://blog.isquaredsoftware.com http://blog.isquaredsoftware.com .
- joevandyk 9y agoNothing is stopping you from putting the functions into multiple files.
- johnfn 9y ago> you have to switch to the one file where you keep all the data-modifying functions? Seriously?! Of course not - and I strongly urge you to think through things like this more deeply before writing them off. Redux is a really good and well-thought-out library. I'm sure you could think of multiple solutions to the problem you just proposed, including splitting that file into multiple files. It would be a shame if you never took the time to understand the library because you got caught up on simple trivialities like this.
- tarr11 9y agoI like this article. It's probably a good idea to build your own simple todo app using Redux from scratch first, and then follow this guide. It would make a lot more sense. Using this as a place to put some thoughts on Redux after having picked it up over the past few weeks. I have been spending the least few weeks re-writing an "offline-first" mobx React app into Redux, after it started spinning out of control and becoming unmanageable. Mobx provided a lot less guidance on how to structure a larger app (read: more than a few pages with non-trivial remote interactions) Like React itself, it took me a few weeks to grok the philosophy and architecture, and internalize the key components so that I wasn't getting lost every few lines of code. I had evaluated Elm earlier in the year but passed on it, as there were some interop issues, and the component ecosystem wasn't as mature as react. Redux has had the effect of organizing my code and helping me reason about the structure, as well as providing time travel for free. Typescript to be very helpful when building with Redux, specifically when I did something wrong, and had to refactor. I've also been pleasantly surprised at the middleware ecosystem, and how useful and easy to configure it has been.
- Existenceblinks 9y agoFirst I pissed off on Elm, and have been observed many the leader's reasons behind things people do not like. However, it is hard to make arguments against reasons from his point of view (e.g. https://github.com/elm-lang/projects/blob/master/roadmap.md https://github.com/elm-lang/projects/blob/master/roadmap.md) Now, it really makes sense to me that he made it hard on JS interop and discourage js-wrapped packages. We should move forward, even WebAssembly team, as I imply, want to ditch javascript completely (But people don't want to say it out for unhealthy discussion) Here is a talk about what/why/some how/ on WebAssembly https://www.youtube.com/watch?v=OH9NYzH3-74 https://www.youtube.com/watch?v=OH9NYzH3-74 We don't need "component" things in Elm, though if you mean "module", I'm sorry. I really don't understand why people still build things on top javascript that is fundamentally and practically wrong (No need to elaborate _this_!)
- bradmwalker 9y agohttps://martinfowler.com/eaaDev/EventSourcing.html https://martinfowler.com/eaaDev/EventSourcing.html
- antjanus 9y agoI wrote a similar article last month on the same topic but it's much more simplified with CodePens to detail the way: https://antjanus.com/blog/web-development-tutorials/front-end-development/build-alterdux-redux-like-redux-compatible-library-scratch/ https://antjanus.com/blog/web-development-tutorials/front-en... It covers only Redux and not React which I think is a little more useful. It DOES cover Enhancers. Anyways, I've seen this article circulate and I'm glad people are interested in the inner workings of Redux!
- emehrkay 9y agoAm I missing something new with object literals or is this an error: window.state.notes[id] = { id, content: '' };
- lioeters 9y agoIf you mean this line: id, ..it's an "object literal property value shorthand", equivalent to: id: id,
- acemarke 9y agoLooks like a standard ES6+ object literal to me. ES6 allows you to shorthand `{someVariable : someVariable}` as just `{someVariable}` (ie, create a key whose name is the variable name and whose value is the variable value). There's some good overviews of ES6's new syntax and features at https://ponyfoo.com/articles/es6 https://ponyfoo.com/articles/es6 and http://es6-features.org/ http://es6-features.org/ .
- emehrkay 9y agoThanks that is exactly what I was asking. I didn't know about that change.
- deleted 9y ago[deleted]
- bpicolo 9y agoRust just added this syntax as well (personally, not a fan). Would rather not have the temporary var in the first place
- RussianCow 9y agoThe syntax isn't meant for you to have to create a temporary variable in order to use it; that would be pretty pointless. It's meant for cases when you already have a variable with the same name as the key you want to set.
- sergiotapia 9y agoIf you're looking for something easier to use to help you manage state in your React apps look no further than Mobx. It's pretty incredible how stupid easy it is to use, it kind of feels like cheating. https://stackshare.io/mobx https://stackshare.io/mobx I've tried to use Redux a couple of times but I just spent way too much time in plumbing code. Code I really don't care about. To be frank this code looks terrible (no fault of the author): const handlers = { [CREATE_NOTE]: (state, action) => { ... }, // ... a thousand more of this } Not to mention, I never not once felt happy working with Redux. I'm all about developer UX and working with tools that feel nice to use. With Mobx you just declare a variable as Observable, then mark your components as Observers, and voila: You have crispy, no-plumbing reactivity. In a way it kind of feels like Meteor where you save data on the database and it replicates everywhere it's being used.
- dxhdr 9y agohttps://github.com/mobxjs/mobx/blob/gh-pages/docs/best/react.md https://github.com/mobxjs/mobx/blob/gh-pages/docs/best/react... "MobX usually reacts to exactly the things you expect it to. Which means that in 90% of your use cases mobx "just works". However, at some point you will encounter a case where it might not do what you expected. At that point it is invaluable to understand how MobX determines what to react to." I'm going to be tossing and turning tonight trying not to dream about libraries that usually work 90% of the time.
- WA 9y agoThis isn't about working only 90%. It means that it fits your current thinking to 90%. Only in 10% of your use cases do you have to dig deeper and actually understand how MobX works.
- bunkat 9y agoThis was a similar promise with the Angular digest cycle. I'll take verbose boiler plate over that any day.
- twfarland 9y agoYou can replace redux with any FRP library. Your state is a signal/stream/whatever that folds over an initial state with a signal/stream/whatever of actions/messages. Your top level view component should listen and render based on that. Example: https://github.com/twfarland/sprezzatura-acto-mario https://github.com/twfarland/sprezzatura-acto-mario
- lomnakkus 9y agoYeah, I'm pretty amazed at the amount of attention that a simple "fold"[1] gets in JS-land. Yeah, OK, Redux (etc.) is also a little bit of a pattern for sort-of-algebraic data types, but really... I prefer using a language that actually supports algebraic data types natively like Scala.js, Reason, Bucklescript, js_of_ocaml or GHCJS. I appreciate that these may not be an option for everyone, but at least one of them should be an option for the vast majority of current frontend developers. [1] Well, technically I guess it would be a foldM?
- antouank 9y agoOr do yourself a favour and use Elm.
- jhund 9y agoOr https://github.com/Day8/re-frame https://github.com/Day8/re-frame
- deleted 9y ago[deleted]
- mal34 9y agoMaking simple things Complex !!
- tomwilson 9y agoYeah, while (hopefully) making complex things manageable.
- dclowd9901 9y agoWrote a similar piece last year if you like this kind of thing. I love learning stuff by implementing it myself: https://medium.com/@davedrew/lets-write-redux-975609b0358f https://medium.com/@davedrew/lets-write-redux-975609b0358f
- msoad 9y agoI have to deal with Redux at work and I absolutely hate how much code I have to write to flip a binary in my React component! I used MobX on the side projects and I absolutely love it! I might be biased but I think MobX is so much better for any size project. Redux is just too good at marketing and their "Hello world" looks very very interesting and reasonable but it doesn't scale. When you have multiple people working on the same codebase it becomes a hot mess! If you're starting a project, give MobX a shot and see how it goes.
- nathan_f77 9y agoOh man, everyone's talking about MobX in here, and I've never really looked at it. This looks pretty awesome. I don't particularly enjoy using Redux either, so I think I might try this out on my next project. I'm looking for some replacement libraries from the Redux ecosystem. I've already found https://github.com/pinqy520/mobx-persist https://github.com/pinqy520/mobx-persist, which looks pretty good. What do you use instead of redux-saga or redux-observable? E.g. for async stuff like ajax calls, or listening for events and emitting new events? Concrete example: You want to listen to a variety of events in your app, and send analytics. Some of your analytics events require looking up parts of the state and doing some processing. This is really easy to do in redux-saga, but how would you do this with MobX? Or would you use something else for this? EDIT: Ah, I think I was looking for "autorun": https://mobx.js.org/refguide/autorun.html https://mobx.js.org/refguide/autorun.html
- hippich 9y agoI am not getting fully redux yet, but from my understanding it is sorta like app-wide message bus with message handlers. Is my understanding correct?
- mlsarecmg 9y agoNot really. You have a state model, once you change it a new immutable slice is created, maintaining the nodes that didn't change. That makes it possible to check for changes with reference equality (old === new), which is fast. Components simply pick a portion of state they're interested in and render once it changes. That makes your app transparent, meaning what you see is just a reflection of state. State changes, app reacts, state changes back, app is the same as it was. You can slide through your apps history in dev-tools and see it construct/deconstruct itself, it's also very easy to inspect and see what action led to which result: https://camo.githubusercontent.com/a0d66cf145fe35cbe5fb341494b04f277d5d85dd/687474703a2f2f692e696d6775722e636f6d2f4a34476557304d2e676966 https://camo.githubusercontent.com/a0d66cf145fe35cbe5fb34149... Redux is a pattern basically, it's pure javascript, no magic, and little behind the scenes stuff.
- o_____________o 9y agoWe've reinvented Windows registry in Javascript, yes
- joshwcomeau 9y agoTFW you see a thread about Redux, and you just _know_ that the comments are going to consist of nitpick complaints. Contrarian opinion (apparently): Redux is a lifesaver when it comes to complex applications. There's a little more ceremony, but a lot more organization, a lot fewer bugs.
- justinsaccount 9y agoExactly. I ported something I wrote in angular to react+redux. The angular version was super short and worked most of the time, but I had a bunch of weird state/race conditions/display issues I could never resolve. Porting it to redux meant: Wire up the reducer with enough initial state containing dummy data so render() works correctly. Add buttons that dispatch actions. Use the debug tools to verify that the proper action gets logged. If it's an action like `LOAD_EXAMPLE` verify that `example` contains the expected name of the example. Once the action is being logged properly handle it in the reducer. Use the debug tools to verify that the state is being changed as expected. At this point the feature should be working. old state -> action dispatched -> reducer -> new state. Having things separated like this means that you only ever have 3 kinds of issues: 1) The wrong action is being raised. Solution: Fix the event handlers or the action generator that calls dispatch. If the action is wrong no need to look elsewhere. 2) The reducer is returning the wrong new state. Solution: Fix the reducer. If the action was right and the new state is wrong, the reducer is the problem. 3) The app is rendering wrong. Solution: Fix the component. If the new state was correct but things look wrong, the only possible place the problem can be is the component. Is this verbose? YES! Is this complicated? NO! It's a lot of very simple javascript functions that do one thing at a time.
- deleted 9y ago[deleted]
- shados 9y agoSome people say ceremony and boilerplate. I say transparency and extension points :)
- arbesfeld 9y agoOne advantage of Redux that people tend to miss is the serializable state object which is incredibly helpful for local logging and remote debugging. It's the reason we built LogRocket (though now we have a bunch of other features for general web apps).