Build Yourself a Redux
zapier.com
zapier.com
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.
First we enumerate our actions as constants...
const ADD_TODO = 'ADD_TODO'
Then we need to create an "action creator" somewhere: import { ADD_TODO } from '../actionTypes'
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
Then we need to import that action and dispatch it when we need it... import addTodo from './actions'
dispatch(addTodo(text))
Now even the same nonsense for reducers...1. You can use strings for action types, no more need to import constants.
2. No need for action creators for simple actions, you can just create the action object inline and Flow will validate its shape.
3. You can be sure that reducers are unpacking properties that actually exist from the actions.
In other words, your example could simply be:
// types.js
type Action =
| { type: 'ADD_TODO', text: string }
// TodoList.js
dispatch({ type: 'ADD_TODO', text })
...and Flow would confirm at 'compile time' that it matches the contract dispatch expects.This approach has scaled up extremely well for me and no longer feels verbose.
And then I found myself writing action creators on purpose, not because I saw it in some tutorial, but because it actually does remove some duplication.
This was also missing from my education for a long time: https://github.com/acdlite/flux-standard-action#actions
I had no idea why I was using a "payload" key, instead of just putting all the values in the top-level object. But this convention makes a lot of sense now.
That said, you are absolutely encouraged to abstract over that process as much as you want! For example, the https://github.com/acdlite/redux-actions library will generate both the action constants and the action creators for you, and there's many more similar utilities.
1. Write helpers. 2. Write middleware.
The first is zero magic, and allows you to opt-in to abstractions as needed. The latter is more powerful and can remove pretty much any boilerplate, but you have to be careful about introducing too much magic.
Redux isn't much different than any other code you might write. If you prematurely abstract, you could create a leaky abstraction, and you'll have to unroll the whole thing. If you don't abstract at all, and copy-pasta everything, you're also going to have a bad time.
- Put all the action types, action types, and reducers for a given portion of the application into one file. This is known as the "ducks" structure, per https://github.com/erikras/ducks-modular-redux .
- Use a utility library like https://github.com/acdlite/redux-actions to generate action types and action creators for you
- Write middleware to manage common logic for your application such as API calls
- Skip writing action creators and declaring action constants, and just have components do `this.props.dispatch({type : "SOME_ACTION"})`.
I don't recommend the last approach, but it's _totally_ up to you, especially because what you regard as "too much boilerplate" is going to be a personal opinion. One person's "too much boilerplate" is another person's "explicit and easy to trace through the system".
Start with
actionNames.txt
ADD_TODO
REMOVE_TODO
Cat that file to actionTypes.js and actions.js. In actionTypes.js, expand:<line> to:
export const <line> = "<line>"
And in actions.js, expand <line> to something like: export const (camelcase-string <line>) = () => {
return {
type: types.<line>,
};
};
Also instead of importing actions and actionTypes individually, I'll generally do: import * as actions from './actions';
import * as types from './actionTypes';
dispatch(actions.addTodo(...));Also I use my json-mobx library to get serialisation and undo/redo. Example: https://github.com/danielearwicker/baltar
My dream would be to have David Nolen (of ClojureScript) and Michel Weststrate (of MobX) do a panel where they discuss the essential differences and pros and cons of each approach. The philosophies seem at odds, but I think there's probably a core truth that neither side has fully reached.
Also, I think the core lacking thing of Redux is that it isn't really composable like React. I'm really curious to check out https://github.com/FormidableLabs/freactal since it aims to be a fractal (composable) alternative.
(And yes, props to Elm for having a built-in composable architecture.)
MobX makes it very easy to do that inspection between states.
Don't look at mutable state as evil. Redux state is mutable too.
The important point is that the state is _serializable_, meaning it doesn't contain side-effects. That also means NetworkRequests must be replayable.
If your state is serializable, you get immutability out of the box by serializing everthing to JSON and back again.
At first I was perplexed by the boilerplate and the awkward way it seemed like I had to update 5 files just to toggle a view element -- but I figured I just didn't understand yet and one day when I did it would all make sense.
Well... after about a year of working with it, I'll admit I understand it and there is some sense to it, but there really is nothing elegant or likeable about it.
I too have never felt happy working with Redux.
I've got a side project I've been working on and was planning to use Redux since that's what I use at work, but I think I'll take this as an opportunity to try out something else.
It got really popular because a lot of people want that. Typing is cheap. If a bit of boilerplate and a couple of files drastically affect your productivity, you're not solving a hard problem (and if you're not solving a hard problem, which is the common case, there are a lot of other tools better suited for it).
But because it got popular, everyone jumped on the wagon, including people who were not the target audience, or were not solving problems it was a good tool for. Now, people try to force Redux into being something else, and it really, REALLY sucks at that.
It took me a bit of time to fully understand MobX and I think it's still rough on the edges but its modelisation and usage make so much more sense.
MobX is an elegant solution compared to Redux's brute forcing approach.
https://www.npmjs.com/package/tiny-state-manager
Maybe not for prod, but certainly great for simple uses and a quick start :)
There are also patterns to reduce the import issue. For example, https://github.com/erikras/ducks-modular-redux. I prefer defining my actions with my action creators in one big index, but the point is that there is absolutely a way to mitigate this concern if it bothers you :)
Well, that would be much worse, don't you think?
My point was that having to keep identifiers to everything is silly.
See the second line of the code snippet under "Symbols are completely unique…"
Unless I have misunderstood the spec, to compare symbols you require both the reference and value. Much more preferable than passing around Strings.
1: Implementing Redux is tedious. But it doesn’t have to be. https://medium.com/@jeswin/implementing-redux-is-tedious-but...
I've expanded on that idea for another Electron app I'm working on (http://www.serverwrangler.com) that encrypts the data before saving and has a database "server" in the main process so data is shared between multiple Electron windows of the same app.
"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.
It has delegated properties which are wonderful for redux-style architectures.
How do you deal with the massive size of the javascript that is generated by kotlinJS?
On Android/react-native, the Kotlin parts runs on the JVM directly. I haven't released a KotlinJS-application to the wild yet, but I don't suppose the size is a problem after running it through webpack, uglify et. al.
You are right, the runtime is rather larger though. Do you have suggestions?
Not to mention it's heavily decorator based, which makes things a _lot_ more complex and inter-dependant. No thanks.
Example:
import { observable } from "mobx";
export default class TodoStore {
@observable todos = [];
constructor(props) {}
}
// Elsewhere in a different file, now you just use it.
import TodoStore from './stores/todos_store.js';
import { observer } from 'mobx-react';
@observer
export default class Todos extends Component {
constructor(props) {
store = new TodoStore()
}
addTodo = (todo) => {
store.todos.push({ id: 1, text: "Get Milk" });
}
render() {
return (
// Just iterate over `store.todos`
)
}
}
As you can see you just use the variables and get stuff for free out of the box with no plumbing code except `@observable` and @observer`. What's not to love?- How do two separate components access the one store, singletons?
- If two components observe the same store but render different attributes of it are they both updated when the store is updated?
- Are you limited to modifying your store only in your component?
You can use <Provider> and @inject to put a store onto the component tree and pull it off whenever you need it. It's just a quick wrapper around the React context API.
> If two components observe the same store but render different attributes of it are they both updated when the store is updated?
Yes, this is just how Mobx works. Observations are set up implicitly. You can observe any @observable value or @computed function just by referencing it within an @observer.
> Are you limited to modifying your store only in your component?
Nope, this works with just plain JavaScript. The main library doesn't offer any React-specific bindings (like Redux), so it can be used with anything.
For me? Basically all of that. Also now that code is highly dependent on the framework and tightly coupled.
Observables have their place for sure, I like them as a concept actually, but for me MobX is encoding an anti-pattern I try to avoid.
https://www.joelonsoftware.com/2001/04/21/dont-let-architect...
But the issue here with that is that I can solve the business needs in React+Redux trivially without running into the architectural problems I mentioned in MobX.
So why on earth would I chose the inferior option?
[1] https://egghead.io/courses/getting-started-with-redux
[2] https://egghead.io/courses/building-react-applications-with-...
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.
Funny timing. I was actually implementing SCU using deep obj equality for the first time earlier today. I did understand the desire for immutability, but it didn't seem to be a game changer.
React's `setState()` definitely doesn't care if you mutate or not - you can `.push()` right into an existing array in state, and re-set it into state to queue the re-render.
On the Redux side of things, immutability is important for several reasons. First, pure reducer functions are more easily testable. Second, they enable time-travel debugging - without immutability, jumping back and forth in state would cause the state contents to behave unpredictably, breaking time-travel. Third, the React-Redux `connect` function relies on immutability checks against the root of the state tree to see if it _thinks_ anything has changed, and against the return values of your `mapState` functions as well. If you mutate Redux state, your connected components usually won't re-render properly, because they think nothing has changed.
The assumption is that if two objects are different references, then their contents are also different. It's possible that you could have two different objects whose fields point to the exact same contents, but given a typical application setup that's unlikely. So, a simple `a === b` (or if you're looking at all the contents, `first.a === second.a && first.b === second.b && .....`) is just some quick pointer comparisons in the JS engine. So, at the JS level you don't care what the pointer address actually _is_, just whether the two variables point to different things in memory.
More precisely: may be different.
My conclusions were:
- it's as much of a discipline than a tool
- the complexity must be added by the middleware
I had a similar experience with it coming in to a recently-started React Native project at work, having not seen React, React Native, or Redux before. At first I was fairly confused (see: awful terminology, painful example code which everyone seems to take as gospel and which had, in fact, invaded our codebase).
Then I started to get an inkling that I was being tricked. I looked closer and... it's two event dispatchers. One of which it's mostly up to you to implement (the reducer). Plus a really short list of suggestions for how to write the code (mainly: don't screw with state in certain places/ways). That's it.
It's paper thin and dead simple, but somehow most people come away from the tutorials and docs hopelessly confused. I think there's something deeply and perhaps irredeemably wrong with the docs/tutorials and with the way Redux's proselytizers communicate. I can't figure out how else they could manage to confuse so many people about such a simple thing.
Redux is the polar opposite. No amount of documentation will change that. The faster we accept that not every tool is the right one for everyone, the faster we can make better tools that are great and some stuff instead of being mediocre at everything.
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.
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.
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
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?
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.
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.
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
[1] https://github.com/markerikson/react-redux-links/blob/master...
[2] http://www.thegreatcodeadventure.com/building-a-simple-crud-...
[3] http://blog.isquaredsoftware.com/2016/11/practical-redux-par...
[4] https://github.com/markerikson/react-redux-links/blob/master...
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.
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
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_!)
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?
I'm surprised that didn't pick up more yet.
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.
I'm looking for some replacement libraries from the Redux ecosystem. I've already found 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://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!
window.state.notes[id] = {
id,
content: ''
}; id,
..it's an "object literal property value shorthand", equivalent to: id: id, const id = getId();
let obj = {id, otherProp: 'something'};
vs let obj = {id: getId(), otherProp: 'something'};
?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...
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"...
If the content is not appropriate to make it a relevant addition to the discussion, then that should be the point of contention, not merely that you've seen it before.
Besides the above, both react and redux have excellent official documentation, and tutorials get stale.
That said, the official tutorials and reference sections can only cover so much info, and other articles often go into more detail. For example, the React docs discuss the idea of "controlled inputs", but Gosha Arinich's series of articles on React and forms [0] go into much more detail on the concept and how to apply it. The React docs mention immutability somewhat in the "Optimizing Performance" section, but there's other articles that discuss the why and how in greater detail [1].
Similarly, the Redux docs try to teach the basic concepts and important principles, but articles like "Redux Step by Step: A Simple and Robust Workflow for Real Life Apps" [3] and "Advanced Redux Entity Normalization" [4] go into a lot more detail on some useful real-world concerns.
In the last couple big React-related threads on HN, some people complained that there were no all-encompassing guides for React, the way there are for things like Django or Rails. A lot of that is because Django/Rails are much more convention-driven, so there really is more of an "official" way to do things. With React, people are free to pick and choose the pieces they want, and that means that a single guide is somewhat impractical. (The React team also does not want to try to push or enforce specific tools as "blessed", partly because Facebook has its own ways of using React that are different than the community, and also because they believe in letting the community build things that solve their own use cases.) As a result, in a lot of ways my list is about as close to a "guide" as you're probably going to find for React best practices and resources.
[0] https://goshakkk.name/on-forms-react/
[1] http://reactkungfu.com/2015/08/pros-and-cons-of-using-immuta...
[2] https://hackernoon.com/redux-step-by-step-a-simple-and-robus...
[3] https://medium.com/@dcousineau/advanced-redux-entity-normali...
It's really a case of XKCD's "Today's 10,000" ( 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.
I'd also welcome any help maintaining the list (organizing, updating, pruning, etc), because thus far it's been only me :)
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 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!
The essential part of Redux is only 44 lines of simple code [1]. You can understand everything that it is doing. That is simple. It doesn't mean that it's going to be a great experience to work with (you might want to add some abstraction on top to make it also 'easy'), but it is definitely simple.
[0]: https://www.infoq.com/presentations/Simple-Made-Easy
[1]: https://gist.github.com/gaearon/ffd88b0e4f00b22c3159#file-sl...
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-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 .
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.
It might be well thought-out but it's more complicated than it needs to be.
I reiterate myself: you should try to understand Redux more deeply before writing it off. You are doing it a disservice.
In Freezer, you can do transactions directly in your view event handlers, and one transaction is one update, and .on('update', (currentState, prevState) => {…}) you can save the prevState into your undo log. And when you want to separate a data manipulation action, you can use custom events to do so — but you aren't forced to! It keeps simple operations simple.
I'm going to divert the conversation away from Redux entirely if that's the case. You should invest in an editor with good "go to definition" support. I had a similar problem, but as soon as I did this, the pain threshold for switching files dropped to nearly 0.
(If that's not the case, do keep on mind that a file separation is totally unnecessary. You could write your state manipulators inline if you wanted. I feel it is a bit organizationally messy, but hey, whatever you like.)
I'm just excited about Freezer, and don't care much about Redux.
It'd all live wherever you like, and be passed on to the master reducer via dispatch. Handler/"action"/reducer could live together, as you please.
It's possibly I'm wrong, as I've never done this, but I don't see why this or something fairly similar couldn't work, with little set-up.
Yes, you can write bad Redux code. That doesn't mean it's not simple.
Redux is way too simple to justify the amount of writing there is trying to teach people to use it[0]. It's two event/message dispatchers. Events/messages move through them thusly. Here's the tiny interface by which you interact with them. Don't do this or this unless you want bugs to happen, and here's why. Done.
[0] a sure sign FP-fans are involved [rimshot]
(Seriously, I mean it - most of my work as a Redux maintainer has involved improving the docs, and I genuinely am interested in having people help improve them.)
"Reducers" come from the similarity with the callbacks passed to `Array.reduce()`, "thunk" is an existing CS/programming term, and "saga" was also adopted from the backend world. So sure, a lot of these terms are new to most people (especially front-end developers), but they were generally based on existing terminology and not just picked out randomly.
It reminds me of Haskell, where monad is such a terrible name. Same with functor, applicative functor, etc. Yes, all these names aptly and mathematically describe what they do, but the most precise name will not help beginners understand.
For instance, if reducers were called "state updaters", I think people would be less confused. Same if "map state to props" was called "get props from state".
Sometimes you gotta give up on giving the most precise name and instead give a name that is the most clear for the greatest number of people.
Many programmers are bad at naming things. Many are bad at doc. None of this stuff is actually hard, it's just made hard and made unfriendly in unfortunate ways.
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/a0d66cf145fe35cbe5fb34149...
Redux is a pattern basically, it's pure javascript, no magic, and little behind the scenes stuff.