Best approaches to build powerful react+redux applications
Due to the deluge of tools and libraries available today, it is quite easy to get confused about when to use React or a combination of React+Redux in building web applications. That is the exact premise of this blog, to clear the clutter surrounding React-Redux and provide you with the best approaches to build powerful applications with them.
If you are planning to use React and Redux together, it is better to use React-Redux, as it is the official Redux UI binding library for React.
Component reuse and optimization with React-Redux
It is possible to write big React components, which are capable of managing a multitude of different tasks, however, it is better to divide the components on the basis of responsibility. This drives the practice of creating and implementing robust React architecture. On the basis of divided responsibilities, React has container components and presentational components – the former collects and manages data and the latter displays relevant information in the UI, based on the data received.
Container components are stateful and presentational components are stateless and are written as functional components, unless they require state and lifecycle hooks. The flow chart below illustrates how container and presentational components interact with the Redux store:
For presentational components, it is better to use a class-based component as shown below:
For container components, it is better to use a class-based component as shown below:
- It is easy to test a component, if it is written as simple as possible by splitting presentational components and container components.
- Previously, React had stateless and stateful functional components. After the introduction of React hooks, the use of State Hooks has made it possible to add state to functional components. So, it’s up to you to decide between functional components and class-based components, based on the requirement.
In the DOM updation process, React starts by rendering the component and then checks for any similarity with the prior render. If the two render results are dissimilar, React updates the DOM. The render comparison process is quick, but it can be made faster with ‘React.memo()’.
With ‘React.memo()’, React renders the component and commits the result to memory. If the props of the current render and the previous render are the same, React reuses the memorized result. The following example demonstrates how this can be done:
Use bindActionCreators to dispatch actions
Dispatch action is a way to change the state in Redux. Typically, dispatch is directly called on the Redux store instance. As an alternative, the Redux utility ‘bindActionCreators’ can be used to send action creators to a component that is not familiar with Redux. In React-Redus, often this is used with the connect() function, as part of the mapDispatchToProps parameter.
So, avoid this:
Also, avoid this:
Instead, do this:
In the above code, ‘filterTalentPoolDataBySkills’ in ‘bindActionCreators’ is available as ‘props.filterTalentPoolDataBySkills’ to dispatch the action. It will make it easier to maintain the code in the long run.
Try to avoid using setState and component lifecycle hooks when using Redux:
Manage the application state using the Redux store, when it is in the global state. Try to avoid using ‘setState’ in your component, when using state management libraries like Redux. Use the component state when it makes sense. For example, to have a mouse over tooltip in a button component, do not use Redux.
Avoid doing this:
Instead do this:
In the above example, the Redux store is used to obtain the state and render it directly in the view. There is no need of using setState and component lifecycle hooks again. Redux is available to execute the task of state management.
Best ways to use .bind():
There are two ways to bind the custom component:
1. Binding them in constructor:
With the above method, only one extra function is created at the time of component creation and that function is used even when render is executed again.
2. Binding at the time of passing as prop value:
In the bind method, every render action results in the creation of a new function. In small applications, it is hardly noticeable, but it might impact large applications. it is not recommended to bind a function at the time of passing as a prop value.
- Its better to bind custom functions in constructor.
- Use Babel plugin, known as Class properties transform, to write the auto-bound function using the fat-arrow syntax.
In the above code, there are no functions to bind.
Use Accessor Functions
For better code refactoring, move all functions, which perform filtering, parsing, and other data transformation logic, into a separate file, and import the file to use the functions inside the connect method of React-Redux:
The above method makes it easy to add flow types for your functions.
Write cleaner code using ES6 Features
Writing cleaner code will make the developers life easy to understand and maintain the code. ES6 features provide a much cleaner way of writing code in React.
Use Destructuring & spread attributes
Instead do this:
Use Arrow functions:
Instead do this:
Use Flow Types
One thing is certain, type checking is expected to be the future of JS. Generally, developers are confused about what to implement between flow and typescript and how smoothly they can be integrated into a current project.
Typescript is more sophisticated to integrate into a current project and the flow feels simple to introduce, although it might be inspecting less of your code as expected.
Benefits in using flow:
- On time detection of bugs or errors.
- Communicates the purpose of the function.
- Scales down complex error handling.
- Wipes out runtime type errors.
Use axios library for HTTP requests over jQuery Ajax:
Fetch API and axios are the most preferred methods to make HTTP requests. Between these two methods, advantages of using the axios library includes:
- It can transform response and request data.
- It allows you to alter the request or response entirely (headers as well). It also performs async operations before a request is made or before a Promise is settled.
- Built-in XSRF protection.
Use styled-components to style your components
The primary purpose of styled-components is to enforce best practices by eliminating mapping between styles and components. This way, you can co-locate your components with their corresponding styles, resulting in localised class names that do not pollute the global CSS namespace.
If you decide to use styled-components, do not forget to install this plugin to support syntax highlighting in strings or maybe help creating a new one. For example:
Test your React components
The goal of unit testing is to segregate each part of the program and test them, so that the individual parts are working correctly. It isolates the smallest piece of testable software from the remainder of the code and determines whether it behaves exactly as expected. Also, you can find bugs at an early stage.
Use ES Lint for better coding conventions.
Well run projects have distinct, consistent coding conventions with automated enforcement. Besides checking style, linters are also excellent tools to find certain classes of bugs, such as those related to variable scope. Assignment to undeclared variables and use of undefined variables are examples of errors that are detectable at lint time.
We have discussed about the different ways to get the optimal performance out of React-Redux and the advantages of such methods. However, you will have to correctly assess whether or not your application needs to have Redux. In simple terms, If your application needs a robust state management tool, Redux is the best available option.