Note by the frontend architect # 1. You can’t just get and use Redux.
Dear Reader! If you have no idea what React and Redux are, reading further does not make sense, further technical nonsense. I seriously, understanding what this note is for, requires working with these libraries - despite the fact that I will try to write clearly, this article is not an entry-level one. And this is personal experience and opinion based on practice.
What is wrong with using Redux?
Then I decided to write, but what is actually wrong with using redux in my project and thousands of others? I’ve been writing react / redux applications since April 2016 (three years). It’s time to already discover some interesting things ... And then there were lectures and reports, especially aimed at beginners, but there wasn’t any adult look back and no retrospective. In the meantime, someone puts asterisks in packages that check "aren't you 13 an hour," I will break the wall of prevailing stereotypes.
But redux is not needed!
You say, and in some ways you will be right. You can’t use it since 2018 - there are a ton of articles on this topic on the Internet, but so far with the “non-use” you get a collective farm, it will become clear below why. And the number of alternatives is off-scale and even more so.
We use Redux, because it is an accepted standard (at least for react), the predictability and reliability that Redux has are important to us. But we seriously miss it, actually in this
Probably, to make it clear what the claim is about the points, you first need to return to the past, to the roots, as you like, namely, open the documentation of the glorious redux and read the postulates. I will consider only the first of them. If it will be interesting to you - share in the comments, I will analyze many more points.
The only source of truth ...
Here we have an ambush. Of course, it says that there can be 1 story, redux declares its difference from flux architecture in this way. But if you look more broadly: is the rule observed in a real project? You will say: quite. I declare (declare) 1 side, I pass it to the provider and then ...
Technically, the process is described correctly. But I can say that people are subject to distortions of perception, logic, and since programmers are still people ... Well, you understand what I’m leading to (if you didn’t understand: programmers are prone to distortions of perception, logic, etc.)
The main distortion here in the fact that I, like many of my colleagues, are used to the fact that if we do not use the term “store” in relation to anything other than redux, then there are no others.
And here comes the reaction
One technical feature called internal state wanted to spit on this postulate. It simply creates a stor of type internal state in any convenient place. There is a component - there is a state that has a mechanism for updating and influencing the component. The difference in use (store state, update and broadcast changes) is almost invisible. You can object: it is not entirely clear why you do not like the component state. He is not like editors, how can they even be compared! It is internal, well, what flags to store there.
Understand that the essence does not change from the fact that you rename the item. There is a sledgehammer Monday, this does not make it the day of the week. Yes, both Mondays are hard, other days and sledgehammers are easier. But from its name, the sledgehammer does not cease to be a percussion instrument.
The scale of redux and state react component is different, but the essence, when used today, is one.
I will explain it this way: in most cases the data from the internal state of the component goes to the child via props, but, no matter how obvious it is, redux data, when integrated with react, also get into the components through props. From the point of view of the component that accepts props, it doesn't matter what is outside. That is, for the end user - that redux store, that internal state - is the same.
Also, this internal state may not depend on the props of the component in which it is declared. Then we get isolation that makes such an internal state an even bigger store than you might imagine.
In order for it to be truly internal, it should only affect the component where it is declared, without giving leaks to the child components. Difficult? Quite, because its meaning is almost completely lost. This is another sign that the internal state is a store. After all, we simply removed one point from the purpose of “storing the state, updating and broadcasting changes” - broadcasting the changes. Everything, the state is lost.
That is, the main problem with having an internal state is that it competes with redux for data, loses in the long run, and crap. We have all sorts of techniques like lift state up (this is when the sibling of the host element is needed, so the state part and all the logic of working with it are taken to the parent, spending a lot of time rewriting and testing the working logic), etc. Bugs and overhead appear in improvements and a lot of joy. This is all the noise that spoils our software at the development stage. We have not reached sales, but the software is already like that.
That is, for all the signs and problems, we have more than one story and many problems associated with this. The final thing, probably, will be the following:
I also love redux for the kind of devtools it has. When I started, we used a logger that simply consolidated all the actions, without giving, however, a complete picture of what was happening. Now - this is the main assistant and friend. At React, they are also represented. In general, devtools is the reason why any pubsub is far from Redux. Like an ant to a blue whale.
Problems (there will be no DNA proofs):
- changing the internal state through react devtools sometimes does not lead to an update or the desired result - I sin on integration with redux.
- internal state breaks timetravel in redux devtools. The super feature with time travel available through redux architecture does not work thanks to react internal state architecture. Internal state just did not care about a change in redux, it has its own state. Timetravel just does not work out. Some elements are simply not updated, partially updated, etc. All this epic with asynchronous code synchronization down the drain.
An example, of course, sucked from practice
You are working on a new project for you, or your colleague wrote some functionality a year ago, and now you need to expand it. In general, there is the task of finalizing someone else's code. You begin to investigate, and understand that there is no data in the editors. There are no actions, reducers in the code that store the data you need. And you begin the journey through the tree of components in search of the treasured and find them (!!!) even a few pieces. You ask colleagues, but the answer is standard: I don’t remember writing to the state faster, we didn’t have time and so on. You go to the source and understand that its current state does not involve revision. You are rewriting working, tested code to make changes and add new functionality.
The presence of a pernicious alternative in the form of an internal state does its dirty deed. After all, now it’s cheap, and it doesn’t matter what happens in a year.
It looks like bad food - it seems tasty and cheap, but after a year or 3 - the gastrointestinal tract ceases to obey and lives its own life. You spend a lot of time and money on regaining your former health and not always succeed in this.
Redux and React Internal State are competitors , as large and small businesses in one niche. The main product is data and influence. Software is the consumer of their products. There are many analogies, but the essence remains the same - when we develop software - we do not need competition.
We are the “dictators” of the program code and any competition should be suppressed, the free market should be prohibited, and the planned economy and state monopoly should dominate the consumer.
Ahem, something bore me. Everything should go according to plan, in general. We have sprints, releases, and more, and the software has a finite cost and a lifetime / entry into the market. This is very important, and we cannot allow the riot on the ship, the uprising of the libraries.
The conclusion is simple.
Do not use other repositories with redux. Exceptions can make only very isolated cases. For example, components that in principle are not controlled by redux without the corresponding layer and do not affect it.
I developed the standalone module in one branch and refactoring the store in another - in general, my approach to managing the store and state is a separate topic for publication. I started refactoring to the module, but at the time of both the beginning and the end of writing the module, refactoring to the test and to the wizard did not go away. Refactoring is large and requires thoughtful recourse that needs to be planned - in general, you cannot just take and refactor.
Therefore, knowing about the upcoming changes in the store, I did not use it to develop a new feature. This would increase the costs of updating abandoned refactoring and tests at times.
What I did: I signed up for a minimum of data. Data and its structure did not suffer from refactoring, the code that generated them suffered, saved, etc. I did not write a byte to the editors. I check if the user is logged in and a couple more fields.
For my needs, I washed PubSub with channels and a simple API. Yes, yes, pubsab. Lack of normal painful pain. Time Travel - Pain. In general, I plan to write an extension for chrome in the form of devtools and it is possible to publish reimplementation as a competitor to redux on the github. I have a ton of complaints about redux, which I will not raise in this article, but PubSub practically does not have them. In addition, I remembered redux logger ...
And so the module has its own storage, its own connection to the server.
That is, redux does not affect the module at all, practically cannot affect this storage (there are only three fields in the subscription), but the module and PubSub do not affect redux in any way. This separation excludes competition.
The question “where to store the data?” During the development of the module I have never had. But when it comes to redux vs internal state - for many this question arises almost constantly. I decided to answer this question once and for all.
My architectural opinion is this:
Store data only in redux (all-all, even "internal"), if it is connected to your react-project as the main repository, do not use repositories that will compete with it. This will increase the reliability and impact of this library and its devtools (time-tracking and tracking of all the data in steps speed up the development and search for possible problems - synchronous changes are steeper and easier to asynchronous).
Perhaps it is worth adding a library that completely excludes internal state from development? Or replaces the internal state with a selection from redux, for example? I started writing one such a year ago, finished 90 percent, and even conducted 1 report. What do you think? Need those?
I hope you enjoyed this note :)