Why do we disable actions and reducers in the Flux / Redux architecture?

I have been using Flux first and Redux later for a very long time, and I like them and I see their advantages, but I have one question:

Why do we separate actions and reducers and add additional calls between calls that express an intention to change the state (action) and the actual way of changing the state (reducer), so that it is more difficult to provide static or temporary guarantees and error checking? Why not just use methods or functions that change state?

Methods or functions provide static guarantees (using Typescript or Flow) and runtime guarantees (method / function not found, etc.), while an action that is not processed does not cause errors at all (either static or time execution), you just need to see that the expected behavior is not happening.

Let me demonstrate this a little better with our Theoretical State Container (TSC):

  • It's super easy
  • Think of it as a React Component state interface (setState, this.state), without any rendering part.

So, the only thing you need is to cause a re-visualization of your components when the state changes in our TSC and the ability to change this state, which in our case will be a simple method that will change this state: fetchData , setError , setLoading , etc.

I see that actions and reducers are the decoupling of dynamic or static code sending, so instead of calling myStateContainer.doSomethingAndUpdateState(...) you call actions.doSomethingAndUpdateState(...) , and you allow the whole thread / reduction mechanism to use this action to the actual state modifications. All of this also introduces the need for thunks, sagas and other middleware to handle more complex actions, instead of using just plain javascript control flows.

The main problem is that for this denouement you need to write a lot of things to achieve this denouement: - the interface of the action creator's functions (arguments) - types of actions - fighting - the form of your state - how you update your state.

Compare this to our theoretical state container (TSC): - the interface of your methods - the form of your state - how you update your state.

So what am I missing here? What are the benefits of this denouement?

This is very similar to this other question: Reducing actions / gears compared to setting state

And let me explain why the most voted answer to this question does not answer either my or the original question: - Actions / Gearboxes allow you to ask questions "Who and how"? this can be done using our TSC, this is just an implementation detail and has nothing to do with actions / gears. - Actions / Reducers allow you to return in time with your state: again, this is a matter of implementation details of the state container and can be achieved using our TSC. - Etc: orders for state changes, middleware and everything that is currently achieved through actions / reducers can be reached using our TSC, it’s just a matter of its implementation.

Thanks a lot! Fran

+5
source share
1 answer

One of the main reasons is that the restraining state changes that must be performed through actions allow you to process all state changes that depend only on the action and the previous state, which simplifies the thinking about what happens in each action. The architecture of the "trap" of any kind of interaction with the "real world" as a creator of the action. Therefore, state changes can be considered transactions.

In your theoretical state container, state changes can occur unpredictably at any time and activate all kinds of side effects, which complicates their reasoning, and errors are much more difficult to find. The Flux architecture forces state changes to be treated as a stream of discrete transactions.

Another reason is to restrict the flow of data in the code in only one direction. If we allow arbitrary changes without restrictions, we can get state changes by causing more state changes, causing more state changes ... That's why this is an anti-pattern for sending actions to the reducer. We want to know where each action comes from, and not create cascades of actions.

Flux was created to solve the problem on Facebook: when some kind of interface code was launched, this could lead to a cascade of almost unpredictable side effects, each of which causes each other. The Flux architecture makes this impossible, making every state transition a transaction and data flow unidirectional.

But if the template necessary for this bothers you, you may be happy to know that your “Theoretical State Container” more or less exists, although it is a little more complicated than your example. It was called MobX .

By the way, I think you are too optimistic with all the "implementation detail". I think that if you tried to actually implement debugging while traveling for your theoretical state container, then what you end up will really be very similar to Redux.

+2
source

Source: https://habr.com/ru/post/1267197/


All Articles