Functional components are some of the more commonly used components in ReactJS. Most developers prefer using functional components over class-based components for the simple reason that functional components require less coding (on the developer’s part). However, two main features for the class are lost when one goes with a functional component – a dedicated state which persists through render calls as well as the use of lifecycle functions to control how the component looks and behaves at separate stages of its lifecycle.
Since version 16.8, a new feature called hooks was added to ReactJS which exposed the various features of class-based components. The two most used hooks are the useState() hook, which allows functional components to have a dedicated state of their own, and the useEffect() hook, which allows functional components to manipulate DOM elements before each render (almost like one gets to do it in lifecycle functions).
useState() hook allows one to declare a state variable inside a function. It should be noted that one use of useState() can only be used to declare one state variable.
Example: Program to demonstrate the basic use of useState() hook.
The value returned by useState() consists of an array with two values. The first value is the initial (or starting) value of the state variable, while the second value is a reference to the function that can be used to update the variable. One can always use array destructuring to assign both values at once so that they can be used in the component. Of course, they can also be assigned separately by assigning a variable with useState() and assigning its first index to one variable and its second index to another (destructuring just makes this easier).
Example: Program to demonstrate the use of a state variable in a functional component and how to update it accordingly.
The working of useState() might seem weird at first. After all, with every render, the function being rendered is a new one – how does the ‘state’ persist then? Behind the scenes, there’s an object representing the functional component in the memory, which has a stack of its own. Whenever the useState() hook is used, the value of the state variable is changed and the new variable is stored in a new cell in the stack. The stack pointer is incremented simultaneously to point towards the last cell. The value pointed to by this stack pointer is used after every render. On a deliberate refresh from the user, the stack is dumped, and a fresh allocation in the memory is done when the component is rendered.
Example: Program to demonstrate the use of last value while updating the value of the ‘state’ variable.
Note that in the above example, we are using an arrow function inside setClick() that fetches the previous value of click and uses it to update it with the new value. This form is useful in cases where it is necessary to perform data manipulations based on the value of the state variable. Passing a function is also useful in cases where one of the older values from the stack is captured and changed instead of the most recent value.
State variables can be arrays too. This is especially useful when one needs to deal with multiple values without finding the need to declare multiple state variables using useState().
Example: Program to demonstrate the use of arrays as a state variable (using useState()).
useState() works differently from the setState() function (which is used to change the value of state variables in class-based components) when it comes to using arrays. setClick() does not merge new values with the existing ones on being called, it simply overwrites them with the new value. Hence, it is necessary to find a workaround for appending the existing values, which is done inside the addNumber() internal function with the help of the spread operator. The function creates a new variable with a certain id and value and adds it to the existing array (whose values are copied into the function using the spread operator).
If one needs to deal with multiple types of data at once, the best way to go for is with an object. While the same work can be done with separate state variables, objects make work much more efficient in the long run (also one can make do with fewer useState() declarations).
Example: Program to demonstrate the use of objects as a state variable (using useState()).
In the above example, the ‘data’ variable is used to temporarily store the entered values for the username and password fields. The spread operator is used again, to copy the existing value of the fields and update it accordingly. The ‘form’ variable is used to store the value of the values submitted through the form used in the component – which is then displayed below the form. Note that the spread operator isn’t used with setForm() while updating the ‘form’ state variable for the simple reason that one does not need to be bothered about the previously submitted values of the username and password fields.
- ReactJS | useEffect Hook
- ReactJS useContext Hook
- ReactJS useReducer Hook
- React JS useMemo Hook
- React JS useRef Hook
- ReactJS | Introduction to JSX
- ReactJS | ReactDOM
- ReactJS | Rendering Elements
- ReactJS | Components
- ReactJS | Components - Set 2
- ReactJS | State in React
- ReactJS | Lifecycle of Components
- ReactJS | Props - Set 1
- ReactJS | Implementing State & Lifecycle
- ReactJS | Props - Set 2
- ReactJS | PropTypes
- ReactJS | Importing and Exporting
- ReactJS | Calculator App ( Styling )
- ReactJS | Setting up Development Environment
- ReactJS | Conditional Rendering
If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to email@example.com. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.