React is one of the most favored languages when it comes to the development of User Interfaces, as it uses the concept of reusable components. There is a constant flow of dynamic data through react components. Hence to manage this dynamic nature of data, we have state objects. The state object is used to store and manipulate the changing data of any component. State also ensures the re-rendering of the component to the browser in case of any change. Hence, the User Interface in React applications becomes a function of the state. This makes the knowledge about state objects and their handling important.
Generally, class components use the state property, while the new function component use hooks to manage the state. Learning state management in class components will help you troubleshoot state management based code and give you an understanding of when we have to make use of class components or functional components.
Now lets us see a class component, and try to get an idea by looking at the code. We will discuss all the parts (state object, props, state) of the code in the later section of the article.
Creating the State Object
To understand what is a state in react. Let's start with its creation and syntax. State object for class based components is initialized in a constructor.
- In the above example, firstly we will make a class App which is extended from the React.Component.
- After that we are calling the parent class constructor using the super keyword.
- Also we are defining the state object which contains the brand of the bike.
The state object can have as many properties as you need.
Using the State Object
We can use the state object anywhere inside the component by using the format given below :
using this syntax we can refer to any of the state-value object attributes.
In the component we have used different state object attributes using the this.state.propertyname syntax.
Changing the State Object
The state of any react component is changed in various cases, such as API response, event handling and props changing. The most reasonable way to handle changes is by using the setState in react. This method ensures that all the updates are made in an asynchronous manner and also ensures that react re-renders that component.
Example: Let us add a button to change the top_speed of the bike from the above example.
The output of the above code changes as the user will press the button to change the speed of the bike.
Few important points related to the state object of the class components :
- React re-renders a component to the browser whenever the state object of that component changes.
- The state object holds dynamic value and can be changed by the user.
- The state object is defined in the constructor of the class.
- The state object is used to store different and multiple attributes.
- To change the value of an attribute of the state object, we use this.setState().
Converting a Function to a Class
Let us look at a brief comparison between the class and functional components so that conversion becomes easy :
|A functional component is a simple js function that returns a react element (JSX) and accepts some props.
|A Class component is extended from the React.Components. It uses the render() method to return a react elements.
|Functional components do not use the render method.
|To return a react element, class component should have render() method.
|Functional components are executed from top to down and are only alive till they do not return.
|Different phases of lifecycle methods keep the class component alive accordingly.
|Functional components are stateless in nature and are generally used to develop UI elements.
|Class components are stateful because they have state and logic.
|Functional components can be made stateful with the help of the react hooks.
|Hooks are not required to manage the state in a class component.
|Constructor is not used in functional components.
|Constructor is used to initialise the state object of the component.
|Lifecycle methods can not be used in functional components.
|Lifecycle methods are used in the class components.
Hence to convert a functional component to class component, we can follow the below steps in their order:
- Creating a class that is extend from React.Components and has same name as of functional component.
- Add an empty render() method inside the class component.
- Move the functional component body into the render() method.
- Add a constructor in the class component.
- convert the react hooks into the lifecycle method.
Example : Lets us take a Functional component and convert it into a Class component.
Functional component :
The corresponding class component will be defined as below:
Adding Local State to a Class
React components mainly depend on the inputs (i.e. props) and state to store and manipulate data. The concept of the local state in react is used to store any information or data that will not be shared with other components. Hence other components do not affect local state value. Whenever the value of the local state of a component is changed, react re-renders that component.
The local state can only be used inside the ES6 classes. To manipulate the value of any attribute of the local state, we must only use the setState in react, as react initiates a re-render of that component every time setState() is executed.
The above class component is acting like a Cookieshop. Hence for someone to buy one or more cookies, the component needs access to the number of cookies (that is, the local state of the component). Now suppose the Cookieshop opens some other branch (that is another class component), and that shop needs access to the number of cookies in this shop which will not be possible in the case of the Local State.
Hence the only disadvantage of the local state is that it cannot be shared with other class components. On the other hand, if we want to track the changes in a state which is isolated to only one component, the Local state is perfect for that scenario.
Using State Correctly
Do Not Modify the State Directly
React maintains two virtual DOMs, one has the changes to be done, and the other is the old version. Both of these are then compared, and the changes are made to the real DOM in the most optimized manner.
So if we change the state directly, it will change the reference of state in both versions, hence React won't be able to notice the difference between the two DOMs as they will be identical. The changes are, as a result, not reflected until we reload.
So, it's obvious from the statement that if we mutate the state directly, it will change the reference of the state in the previous virtual DOM as well. So, React won't be able to see that there is a change of the state, and so it won't be reflected in the original DOM until we reload. The problem is more apparent in Pure Components.
Mutating the state can also lead to bugs, and components cannot be handled correctly and optimally. We might even lose control over the state across all components. Also, there is no point in calling setState in react after changing the state mutably, as it will only replace the state with the same value. No rerendering will occur.
In the above example, we are rendering a list stored in the state as an item array. We have made two functions - one adds the item immutably and the other mutably. On adding an item immutably the state will change and the changes will be reflected but on adding immutably the state will change but the changes will not be reflected.
State Updates May Be Asynchronous
To optimize performance, React might merge two or more setState calls into one. The value of this.state and this.prop may change simultaneously. This might lead to unexpected results.
For example, in the below code the value of state.count may not get updated:
To fix this problem, we need to use a different form of setState() that accepts a function instead of an object. The function has the old state as the first argument and props at the time of update as the second argument.
We have used an arrow function above, but it also works with regular functions :
The state values used within the functional components are from their current closures. Even if the state may have been updated in the background, current closures cannot reference the updated values. In the next render cycle, the updated values are reflected, and new closures are created for these updated values while the current ones remain unchanged.
The value before setting the state and after setting the state is the same. The value of the current state is getting reflected after the next state change. This can be corrected by making the following changes in the code:
State Updates are Merged
Whenever we call the setState() function, React combines the object passed in setState() and the current state.
If our state contains independent variables, then we can call different setState() functions to modify each variable. The value of other keys not passed in the object is not affected and only the keys passed are affected. This way React combines the old state and the changes to create the new state.
In the above code the first setState() function called inside the componentDidMount() modifies the name property of the state and the second one modifies the age property.
The Data Flows Down
The information about a component being stateless or stateful is unknown to the parent or child. The parent and child components should also not care if the component is a function or a class component.
The state is hence encapsulated or local, it is accessible to only the component in which it is defined. A component might pass its state down to child components in the form of props.
This is known as the top-down flow of data. The state is owned by a particular component, and only the elements in the subtree below the component in the DOM tree are affected by the change of state in the component.
In the above example, the name property from the state of the parent is passed into the child component as a prop. The statefulness of a member is an implementation detail of the component. The implementation can be changed over time. Also, we can use stateful components within stateless components and vice versa.
What is the Difference Between State and Props?
|Props get data from the parent component (i.e. from outside).
|State is used to store and manipulate the data within the component (i.e. within).
|Exchange of data between different components.
|It is only used within a component.
|Any data from parthe ent component is read-only and cannot be changed.
|Data can be modified inside the component usthe ing setState() method.
|Initial value is not required but can be passed the rom parent component.
|Initial value is required and received believe the om parent component.
|It can only be read.
|It can be read and modified.
|It is immutable.
|It is mutable.
|It is static and non-interactive.
|It is dynamic and interactive.
Example of props:
Example of state:
- The state object is defined in the constructor of the class component and the parent constructor is called using the super keyword.
- The concept of the local state in react is used to store any information or data that will not be shared with other components.
- State object should be treated as immutable and should be changed using setState() because this method ensures that the updates are made in an asynchronous manner and ensures the re-rendering of that component.
- State updates are asynchronous and are merged by react to optimize performance.
- We can use stateful components within stateless components and vice versa.
- Props get data from the parent component which is read-only and immutable.
- State is used to store and manipulate the data within the component and it is read and written which means mutable.
- A component can pass its state down to child components in the form of props.
- State is dynamic, interactive and can be read or written while props are static, non-interactive and can only be read.