👨🏼‍💻

khriztianmoreno's Blog

Home Tags About |

Posts with tag redux

Redux explained in a simple and succinct way for React developers

2022-08-10
reactreduxjavascript

Redux is a widely used state management library for React and TypeScript applications. It’s easier than ever to manage state in React thanks to the useState React Hook, as well as the Context API. However, when your codebase grows very large, you’ll need a more powerful and structured state management solution, rather than an ad-hoc one. That’s where Redux can help.ReduxWhy do you need Redux?When working with React, you usually end up with state that is used globally throughout the entire application.One of the approaches to sharing state across the component tree is to use the Context API. We often use it in combination with hooks like useReducer and useState to manage global application state.This approach works, but it can only take you so far. In the end, you have to invent your own ways to manage side-effects, debug, and split state management code into modules so that it doesn't become an incomprehensible mess.A better idea is to use specialized tools. One such tool to manage global application state is Redux.How Redux WorksRedux is a state management framework that is based on the idea of ​​representing the global state of the application as a reducer function.In Redux, to manage state, we define a function that accepts two arguments: state, for the previous state, and action, the object that describes the state update.function reducer(state = "", action: Action) { switch (action.type) { case "SET_VALUE": return action.payload; default: return state; } }This reducer represents a string value. It handles only one type of action: SET_VALUE.If the received action field type is not SET_VALUE, the reducer returns the unchanged state.After having the reducer, we create the store using the redux createStore method.const store = createStore(reducer, "Initial Value");The store provides a subscription method that allows us to subscribe to updates to the store.store.subscribe(() => { const state = store.getState(); console.log(state); });Here, we've passed a callback that logs the state value to the console.To update the state, we dispatch an action:store.dispatch({ type: "SET_VALUE", payload: "New value", });Here we pass an object representing the action (action). Each action is required to have the type field and optionally, payload.Usually, instead of creating actions in place, people define action creator functions:const setValue = (value) => ({ type: "SET_VALUE", payload: value, });And this is the essence of Redux.Why can't we use the useReducer hook instead of Redux?Since version 16.8, React supports Hooks. One of them, useReducer, works very similarly to Redux.It's easy to manage application state using a combination of useReducer and the React Context API.So why do we need Redux if we have a native tool that also allows us to represent state as a reducer? If we make it available throughout the application using the Context API, won't that be enough?Redux offers some important advantages:Browser Tools: You can use Redux DevTools to debug your Redux code. It allows us to see the list of dispatched actions, inspect the state, and even travel back in time. You can toggle through the history of actions and see how the state dealt with each of them.Handling Side Effects: With useReducer, you have to invent your own ways to organize the code that makes network requests. Redux provides the Middleware API to handle that. Additionally, there are tools like Redux Thunk that make this task even easier.Testing: Since Redux is based on pure functions, it is easy to test. All testing comes down to checking the output against the given inputs.Patterns and code organization: Redux is well studied and there are recipes and best practices you can apply. There is a methodology called Ducks that you can use to organize Redux code.Building with ReduxNow that you've seen examples of what Redux does and how it works, you're ready to use it in a real project.Profile@khriztianmoren

What is a “side effect”?

2020-02-20
javascriptreactredux

In the previous post, we learned a bit about immutability and why it should matter when writing our code, especially our reducers.This time, I want to talk a bit about side effects and how working with pure functions can help us. However, first, let's see what makes a function pure and why it is closely related to immutability.Immutability RulesTo be pure, a function must follow these rules:A pure function must always return the same value when given the same inputs.A pure function must not have any side effects.“Side effects” is a broad term, but it basically means modifying things outside the immediate scope of that function. Some examples of side effects are:Mutating/modifying input parameters, like giveAwesomePowers (function from the previous post)Modifying any other state outside the function, such as global variables, or document.(anything) or window.(anything)Making API callsconsole.log()Math.random()API calls might surprise you. After all, making a call to something like fetch('/users') might not change anything in your UI.But ask yourself this: if you called fetch('/users'), could it change anything anywhere? Even outside your UI?Yes. It will create an entry in the browser's network log. It will create (and perhaps later close) a network connection to the server. And once that call reaches the server, all bets are off. The server could do whatever it wants, including calling other services and making more mutations. At the very least, it will probably place an entry in a log file somewhere (which is a mutation).So, as I said: “side effect” is a pretty broad term. Here is a function that has no side effects:You can call this function once, you can call it a million times and nothing will change. I mean, technically, this satisfies Rule 2. Calling this function will not directly cause any side effects.Also, every time you call this function like add(1, 2) you will get the same answer. No matter how many times you call add(1, 2) you will get the same answer. That satisfies Rule 1: same inputs == same outputs.JS Array Methods That MutateCertain array methods will mutate the array they are used on:push (add an item to the end)pop (remove an item from the end)shift (remove an item from the beginning)unshift (add an item to the beginning)sortreversesplicePure Functions Can Only Call Other Pure FunctionsA possible source of trouble is calling an impure function from a pure one.Purity is transitive and it's all or nothing. You can write a perfectly pure function, but if you end it with a call to some other function that eventually calls setState or dispatch or causes some other kind of side effect… then all bets are off.Now, there are some types of side effects that are “acceptable”. Logging messages with console.log is fine. Yes, technically it is a side effect, but it is not going to affect anything.A Pure Version of giveAwesomePowersNow we can rewrite our function keeping the Rules in mind.giveAwesomePowers — Pure functiongiveAwesomePowers — Pure functionThis is a bit different now. Instead of modifying the person, we are creating a completely new person.If you haven't seen Object.assign, what it does is assign properties from one object to another. You can pass it a series of objects, and it will combine them, from left to right, while overwriting any duplicate properties. (And by “from left to right”, I mean that running Object.assign(result, a, b, c) will copy a into result, then b, then c).However, it does not do a deep merge: only the immediate properties of each argument will be moved. Also, most importantly, it does not create copies or clones of the properties. It assigns them as they are, keeping the references intact.So the above code creates an empty object, then assigns all the properties of person to that empty object and then assigns the specialPower property to that object as well. Another way to write this is with the object spread operator (spread):giveAwesomePowers — ES6 || spreadgiveAwesomePowers — ES6 || spreadYou can read this as: “Create a new object, then insert the properties of person, then add another property called specialPower”. As of this writing, this spread syntax is officially part of the JavaScript specification in ES2018.Pure Functions Return Brand New ObjectsNow we can rerun our experiment from before, using our new pure version of giveAwesomePowers.The big difference is that person was not modified. Mafe has not changed. The function created a clone of Mafe, with all the same properties, plus the ability to become invisible.This is kind of a weird thing about functional programming. Objects are constantly being created and destroyed. We did not change Mafe; we created a clone, modified her clone, and then replaced Mafe with her clone.I hope this has been helpful and/or taught you something new!Profile@khriztianmoreno �

What is immutability?

2020-02-10
javascriptreduxreact

Immutability in React and ReduxImmutability can be a confusing topic, and it appears everywhere in React, Redux, and JavaScript in general.You may have encountered errors where your React components do not re-render, even though you know you have changed the props, and someone says, "You should be making immutable state updates." Maybe you or one of your teammates regularly writes reducers in Redux that mutate the state, and we have to constantly correct them (the reducers, or our teammates 😄).It's complicated. It can be very subtle, especially if you're not sure what to look for. And honestly, if you're not sure why it's important, it's hard to care.

Flux Standard Action (FSA)

2020-01-20
reactjavascriptreduxtutorial

It is a lightweight specification that defines the structure of an action, to be implemented in libraries that use the Flux pattern or architecture.Compliance with FSA helps developers create abstractions that can work with different implementations of Flux.Flux Standard Action — ExampleFlux Standard Action — ExampleIt all started after Facebook published its architecture/pattern Flux, many libraries implemented the Flux philosophy, Redux was one of them.Flux can be divided into several concepts Dispatcher, Store, Action, and View. But in this post, we are going to learn about the Action part and how to work with them in a more standardized way, so later we can use other libraries that implement the FSA philosophy.Before delving deeper into today's main topic, let's get to know the concept of Action and how it is defined by flux:Actions define the internal API of your application. They capture the ways to interact with your application. They are simple objects that consist of a “type” field and data.The specification would lead to the following object:{ type: 'ADD_TODO', text: 'TODO content' }The only problem with this simple example is that the developer can choose any property name for the values. All the following names are valid: title, name, text, todoName, etc. It is impossible to know what properties to expect from ADD_TODO in the Redux reducer.It would be much easier to work with Flux actions if we could make certain assumptions about their shape. Maybe defining a minimum common standard for these patterns would allow us to have the necessary abstraction to communicate our actions with the reducer. This is something that Flux Standard Action (FSA) comes to solve.To go into a bit more detail about FSA, it is necessary to start from the following premise that Flux Standard Action provides us about actions:An action MUST:be a plain JavaScript object.have a type property.An action MAYhave an error property.have a payload property.have a meta property.An action MUST NOT include properties other than type, payload, error, and meta.But then what does each of these properties that our JavaScript object can contain mean?Let's see each of thesetypeThe required property type identifies the nature of the action that has occurred to the consumer, type is a constant of type StringpayloadThe optional payload property MAY be any type of value. It represents the action's payload. Any information about the action that is not the type or the status of the action should be part of the payload field.By convention, the payload SHOULD be an object.errorThe optional error property MAY be set to true if the action represents an error.An action whose error is true is analogous to a rejected Promise. By convention, the payload SHOULD be an error object.If the error has any value other than true, including undefined and null, the action MUST NOT be interpreted as an error.metaThe optional meta property MAY be any type of value. It is intended for any additional information that is not part of the payload.The Flux Standard Action (FSA) concept is used by some libraries that can help us reduce the repetitive text we have to create for our actions.Librariesredux-actions — a set of helpers to create and handle FSA actions in Redux.redux-promise — A middleware that supports FSA actions.redux-rx — RxJS utilities for Redux, including a middleware that supports FSA actions.I hope to have the opportunity to give an introduction on how to reduce Redux boilerplate with Redux-Actions in a future occasion.I hope this has been useful and/or taught you something new!Profile@khriztianmoreno �