 Okay, hi everyone. Thank you for attending my talk. I don't know if you remember, but there was an interesting trend on Twitter where people wrote their unpopular opinions about different things. The one that caught my attention the most was React Redux Opinions. It was intriguing to know others' people's opinion and sometimes even to relate to them. And because of that, I thought maybe I can share mine through this talk. So I submitted to the DEF CONF and here we are now. So now that I have your attention, I'm going to share with you my unpopular opinions. And what I want you to take from this is that even though I'm using things that are obsolete or irrelevant today, they still can be valuable, especially if you know the trade-offs and you use them with moderation. So without further ado, let's start the talk. My unpopular ReactJS opinions. Thank you. Okay, so let's start with my first unpopular opinion. Redux is not dead. I hear a lot of people bashing and telling how unnecessary Redux is and how they are willing to move from Redux to React Context API. Honestly, I read many blog posts comparing between the two and it feels like it's popular to show that Redux is redundant and explain how to migrate your code from Redux to Context API. Nonetheless, all of them are concentrating on a problem that apparently both Redux and React Context API are solving. And that is prop drill. Prop drill refers to the process you have to go through to get data to parts of the component tree. So for example, you have your app component that has the color scheme and you want to pass this to the toggle buttons and also to the adder and toolbar components. But the problem is that those components are rendered under the sidebar and the page section, which are wrapped in the page layout component. So we basically have three levels to pass these props till we get to final destinations. This problem can be solved by either Redux or React Context API. They both have a storage that any component can read and so no additional props are needed to be passed down. And personally, if this is the problem you want to solve or you're trying to solve, then obviously installing Redux is not the way because you will increase your bundle size, you will have to deal with configuring the Redux store. While in React Context API, you just create a context and pass to it the necessary values, consume it in the requirement components. And that's it, you're good. But we are missing one important idea here. And that is Redux is a state management based on flocks. And because of that, you can travel between the state history and reevaluate the current state. In other words, we can debug issues on our machines by having a snapshot of the initial state and run the same actions that were recorded in the history to reproduce and fix the bug. In addition to that, React Context API is only one part of Redux. You will still need to manage your state, which is done by use state, use reducer and use effect. The way Redux manages the state is also interesting. You have action creators that create actions that describe what is needed to be done. You also have middlewares that take care of the side effects for you and propagate new actions that in turn update the state. So that's my opinion. If your app is complex, and it is not a matter of having isolated state to interact with each other, then be my guest and go with OOX and Context API. However, if stability is much more important to you than speed of implementation or delivering fast, then most of the chances are Redux will do good for you and for your team. This brings me to my second unpopular opinion. I-order components are still useful. So this is something I know many of you will disagree with me. I-order components were very popular back then, until render props came and later on react OOX, which eventually made I-order components a dead shell in the sea. So why am I still using it today? You might ask. So in general, we could break I-order components into two groups. The first is the injectors and the second is then answers. The injectors inject props into erupt components while giving you the ability to massage and fit the props to the erupt components. Then answers on the other hand enhance the erupt components with new functionality. And according to react OOX, this group was meant to replace the mixing pattern that was used. But it has some caveats. The ones that matter to me are that you could override props that were passed by the first or previous wrapper and also composing all these components make the code more magical, which means less readable code and hard debugging. Even though this caveat exists, I still love using I-order components for injecting props. I believe this is one of the easiest ways to do dependency injection. So how do I live with I-order components? I have some rules and they are very strict. One is not composing more than two to three I-order components. For example, sometimes I have to wrap connect inside with router to get both react route and redux props. But most of the time, only connect is necessary. Second, I always use connect as the last wrapper in order to massage all these props to fit the core component. Okay, so moving on to my next unpopular opinion. And that is opinion number three, splitting reducers horizontally. One of the problems I had with redux is code reuse. For example, I had two states that we're using is loading to determine whether data fetching is in progress or not. At the beginning, it looked like a good idea to repeat the same logic and have almost the same actions to update those states because they were only two places and I needed to merge this by the end of the sprint. However, as more and more states in my store were using the same idea, it felt like I'm going to have a problem in the future because what happens if I want to change the logic and to scale it to the other states in my store. So what most of us did, and especially I was writing a high order reducer, which basically is a function that takes a reducer and returns a new reducer that handles is loading actions and logic inside of it. And for other actions, it just delegates to the task reducer to deal with it. This seems like a good idea and a very good solution and made me to realize that I have other items in my states that repeat themselves. And so I ended up with many high order reducers. And as you might guess, I had the same issues I had with high order components, which were hard to read and hard to debug. And you're not sure exactly which reducer updates what and why. What I eventually decided to do is to take a step back and think of a different way. What I realized is, or I understood is that I'm having functionality vertically. And so I decided to break those states that I'm using in multiple places into one place. In other words, I will have one reducer and one state that will manage multiple states that have the same behavior or structure. And so for instance, with is loading, I will have a state that is an object with with keys that are the names or of the namespaces that are using the is loading logic, like users, hosts, and etc. And the value will be true if the data is being fetched, or false otherwise. The action creator is also pretty easy. I will have to, I will have a function that takes the key and the value and will return an object with the action type of is loading. And the pair will be the value true or false. And I will have a meta attribute that contains the key. So I can update the right item in my state. In addition to that, the reducer will have to handle only one type of action. It will take a value from the action payload and the key from the action meta and update the store accordingly. Very easy. And that brings me to my next unpopular opinion, which is don't use is loading, or is open, or is something extensively. Because it is very common to use those flags to determine whether a given state is true or false, as I mentioned previously. For example, the is open prop is used to determine whether to show a dialogue box or not. Another frequently used prop, as you might have guessed, is loading, which is used to determine whether to show a spinner on the screen or not. And so it makes sense to have these two props in a confirmation dialogue before deleting an item. However, I believe that it is easy to read and write the code if those two props were merged into one, unless it is possible that the confirmation dialogue is closed and loading at the same time, which I think it's a real bad UX. And let me suggest the following alternative. Assuming our confirmation dialogue can be one of the following. One, it could be closed when the dialogue is closed. Two, it could be open when the dialogue is open after the user clicked on the delete button. It also can be pending while the request is being processed, and no response was received yet. Failure if the request failed, and we could not delete the item. And of course, success when the request was successful, but actually we will close the dialogue automatically, and we will go back to the closed state. So we will have only four different states. We can get this farther. And when using TypeScript, we can determine the data the payload will contain. For instance, when the status is closed, the payload will be null because we are not showing anything in the dialogue. When the status however is open or pending, the payload will contain the name and the idea of the item because we need to show that in the dialogue message. And when the status is failed, obviously the payload will also contain the error message in addition to those two, because we want to show the error message. And so this will reduce the props that we will pass to the dialogue component. And with that, it will be easy to determine the props we are using in each status. As you can see here, we are using status and payload, unlike before when we used name, ID, and so on. And when we are rendering the dialogue, we can easily understand what is going to happen when the status is not closed, or when the status is in pending or loading state. And also what items are rendered when the status is in failure, or when it's open or loading. In the end, the component is more explicit in regard to different cases, which makes it easy to maintain as well. Okay, so what did we have? One, Redux is a state management based on flocks. Therefore, there is no need to compare between useStateUseReducer and ContextAPI and Redux. Two, Connect is a good, because it keeps the single responsibility and dependency injection principles. Three, keep your reducers small without violating the open close and the single responsibility principles. And the last one, using the idea of finite state machine to determine what states are dealt and their transition is a good thing, because it makes the code more readable and maintainable. The developer know the attention of the component and what's supposed to happen. All in all, React hooks, they are amazing. They are amazing tool, but they are not a silver bullet. The same thing I can say about Redux. And thus, it always smart to design and plan before jumping to write in code. Try to determine or understand what is the problem you are dealing with and what are the solutions and come and see the trade-offs between the two solutions that you need or the tooling that you are using. And by that, yourselves, all the problems of maintaining code that is hard and making the code not readable enough for your team. Thank you so much for joining me.