What is state management?
It is data or information that changes or manipulates throughout the running time of a program. The “status” of a program at a time is a brief description of all the data that the program is currently waiting for or analyzing to proceed to the next step of its implementation.
Each component, module, etc. have its own state. The state can be managed at the component level as we do usually without having complex state management methods. But when it comes to sharing the state between a few components or modules we are having the requirement of a proper state management mechanism.
Flux pattern was introduced to manage the state of the entire application with more control. It was originally designed by Facebook. In Flux, we are keeping the state of the entire application in a separate object called ‘Store’.
The below figure shows the key parts of the flux pattern.
This component renders the UI. Whenever any user interaction occurs on it (like an event) then it triggers the action. Also when the Store informs the View that some change has occurred, it re-renders itself. For example, if a user clicks the Submit button.
This handles all the events. These events are passed by the view component. This layer is generally used to initiate API calls. Once the action is done it is dispatched using the Dispatcher. The action can be something like Submit a form, add or remove a comment, or any other similar user interaction.
This is the central hub and singleton registry. It dispatches the payload from Actions to the Store. Further makes sure that there are no cascading effects when an action is dispatched to the store. It ensures that no other action happens before the data layer has completed processing and storing operations
Redux was designed by partially using the flux pattern. It was initially designed to be used as a state management system for react applications. Redux follows the functional programming concepts.
State in redux is
Writes as pure functions.
Reducers are functions that take the current state and an action as arguments and return a new state result. In other words, (state, action) => newState.
- They should only calculate the new state value based on the state and action arguments
- They are not allowed to modify the existing state. Instead, they must make immutable updates, by copying the existing state and making changes to the copied values.
- They must not do any asynchronous logic or other “side effects”
Types of actions that are available in the application to change the state
In the same way that we designed the state structure based on the app’s requirements, we should also be able to come up with a list of some of the actions that describe what’s happening:
- Add a new todo entry based on the text the user entered
- Toggle the completed status of a todo
The Redux store has a method called dispatch. The only way to update the state is to call the store.dispatch() and pass in an action object. The store will run its reducer function and save the new state value inside, and we can call getState() to retrieve the updated value:
The current Redux application state lives in an object called the store.
The store is created by passing in a reducer, and has a method called getState that returns the current state value:
since redux is based on functional programming.
- Handle Concurrency
- Faster change detection
Can be considered as plus points. But because of the same reason,
- Performance issues
- Memory overhead Also can be expected.
Vuex also partially follows the flux pattern
- The application-level state is centralized in the store.
- The only way to mutate the state is by committing mutations, which are synchronous transactions.
- Asynchronous logic should be encapsulated in and can be composed with actions.
If you are using Vuex, then you will have only one Single store for each VueJS powered application. Vuex Store is a Singleton source of State. Our store contains an application state. State management in VueJS with Vuex is straightforward. You just need to modify the state via dispatching the action and not directly because we want to predict the future states. Our store contains an application state.
At the center of every Vuex application in the store. A “store” is a container that holds your application state. Two things make a Vuex store different from a plain global object:
Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store’s state changes.
You cannot directly mutate the store’s state. The only way to change a store’s state is by explicitly committing mutations. This ensures every state change leaves a trackable record and enables tooling that helps us better understand our applications.
The only way to change the state in a Vuex store is by committing a mutation. We can directly change the state, but we will not do it because we need a snapshot for every step of our project. We need to predict the next state. For the debugging purpose, we will not mutate the state directly, but via mutations.
Actions are similar to mutations, the differences being that:
- Instead of mutating the state, actions commit mutations.
- Actions can contain arbitrary asynchronous operations.
Example for a Code Structure
Vue vs Redux in state management
React is different from Vue in the way it processes updates: React renders a virtual DOM then calculates optimal DOM operations to make the currently rendered DOM match the new Virtual Dom. But it has no way of knowing whether a particular component needs to re-render or not based on the new data. Vue instances keep track of which bits of data they depend on to render. These instances automatically register what needs to re-render when the data changes
One of the contrasts between React and Vue is the way they handle state change. This heavily affects the mechanism behind the UI updates, also known as re-rendering.
React promotes the functional programming (FP) style. It implements FP principles, such as higher-order functions, immutability, pure functions, etc. The philosophy behind React is that the state remains immutable. When trying to mutate the state object, no re-rendering occurs. To trigger re-rendering, the method setState should be used. This updates not only the root component but the entire component sub-tree as well. The re-rendering process can be controlled by using PureComponent or shouldComponentUpdate lifecycle hook. All the optimizations should be done manually. This makes the data flow more predictable.
— Redux Comparison with VueX
Since functional programming concepts are used, encourage to maintain pure functions. Has to use Spread operators to copy the existing state as a new state object when updating the state.
Else Immutable, Immer, or similar 3rd party libraries should be used to achieve immutability in objects.
Since objects are copying each time a performance issue can occur.
- Use single-store
- User reducers
- Have to use more boilerplate code
- Actions and Action Creates that we have to use with reducers are creating more verbose.
- Use single-store
- Use mutations
- State is mutable
- Comparatively very few boilerplate codes
- Mutations are simpler than reducers.
Performance report by Chrome Dev tool
When to use…
- It is crucial to decide when to use Vuex and keep the state inside a separate store. If we refer to some state only inside the component we don’t have to use the store.
- Similarly, since Vuex introduced the module concept, when it is necessary we can manage the state at the module level without keeping it in the root store.
- Also, vue3 provides a strong reactivity system. Further by using provide and inject, we can share the state by making it available to other required components. We can also consider these steps before using the Store.