DEV Community

Cover image for State usage in Functional and Class Components in React
Pavan Chilukuri
Pavan Chilukuri

Posted on • Updated on

State usage in Functional and Class Components in React

I created a Todo app with two approaches namely - class based and functional based approach. The purpose of this article is to compare these both approaches and help you understand the react hooks in functional components, managing state in both class components and functional components.

Class based approach

This is pretty much straight! Create an ES6 class, define its constructor. Declare the state variable in the constructor and assign initial values to it.

export default class Todo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      todo: "",
      todos: [
        { name: "Buy groceries", done: false },
        { name: "Pay rent", done: false }
      ]
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

I created an other component Input, which takes the input value from user (a todo). It accepts a prop named changed and we are assigning the value returned by the ES6 function, handleTodoChange to the prop changed

 <Input changed={handleTodoChange} />
Enter fullscreen mode Exit fullscreen mode

Coming to the handleTodoChange function, it takes one argument, event and it looks for the change in the input field. Whatever the user types, the change is recorded and updated constantly to the todo state variable.

 handleTodoChange = event => {
    this.setState({ todo: event.target.value });
  };
Enter fullscreen mode Exit fullscreen mode

When user hits on Save button, a todo should appear the in the list of Todos. For this, we will handle the save button function as below.

  handleSave = todo => {
    let newCopiedArray = [...this.state.todos];
    newCopiedArray.push({ name: this.state.todo, done: false });
    this.setState({ todos: newCopiedArray });
  };
Enter fullscreen mode Exit fullscreen mode

Instead of the ES6's spread operator (...), you can also use javascript slice() method. It is one and the same.
For instance,

let newCopiedArray = [...this.state.todos];
Enter fullscreen mode Exit fullscreen mode

is same as

let newCopiedArray = this.state.todos.slice();
Enter fullscreen mode Exit fullscreen mode

Functional based approach

With the advent of Hooks, we can manage the State right in our functional components. No more converting the functional components to class components! useState(), useEffect() are few examples of React Hooks. We will be using useState() for now.

Wondering what a "Hook" is?

Hooks are functions that let you “hook into” React state and lifecycle features from function components.

Keep in mind, Hooks don’t work inside classes. They let you use React without classes.

Let us re write the Todo Component as a function and declare the state variables just like we did in the class component.

const Todo = () => {
  const [todo, setTodo] = useState("");
  const [todos, setTodos] = useState([
    { name: "Buy groceries", done: false },
    { name: "Pay rent", done: false }
  ]);
}

Enter fullscreen mode Exit fullscreen mode

If you observe, this is a functional component and with the use of hook, useState() the code looks much clean. Isn't it? Don't worry about the syntax, I'm going to break it down for you going further.

const [todo, setTodo] = useState("");
Enter fullscreen mode Exit fullscreen mode

This is Javascript Array Destructuring concept. From the above line of code, we are creating two new variables todo and setTodo, where todo is set to the first value returned by useState, and setTodo is the second. It is same as the code below.

  let todoStateVariable = useState(''); // Returns a pair
  let todo = todoStateVariable[0]; // First item in a pair
  let setTodo = todoStateVariable[1]; // Second item in a pair
Enter fullscreen mode Exit fullscreen mode

Here's a bonus from React Docs

When we declare a state variable with useState, it returns a pair — an array with two items. The first item is the current value, and the second is a function that lets us update it. Using [0] and [1] to access them is a bit confusing because they have a specific meaning. This is why we use array destructuring instead.

Let's change the handleTodoChange and handleSave functions using state variables.

  const handleTodoChange = event => {
    setTodo(event.target.value);
  };
Enter fullscreen mode Exit fullscreen mode

Instead of this.setState({ todo: event.target.value }); now it is simply setTodo(event.target.value);

Similarly,

  const handleSave = todo => {
    let newCopiedArray = [...todos];
    newCopiedArray.push({ name: todo, done: false });
    setTodos(newCopiedArray);
  };
Enter fullscreen mode Exit fullscreen mode

That is it! You have seen both the approaches and use of hooks in the functional components.


You can checkout the source code here for Class based approach and Functional based approach. Thank you for your time. I hope you enjoyed reading this post. Feel free to write your comments or questions if any.

Latest comments (2)

Collapse
 
kosich profile image
Kostia Palchyk

Hi! Nice article!

Small tip:
to add syntax highlight — just add js or jsx to your code snippets opening backticks.
e.g. '''jsx (with backticks intstead of ')

--

Also, you might not need a state! Check out my experiment with JSX and RxJS:

<div>{
  axios(url).then(r => r.data)
}</div>
Collapse
 
chilupa profile image
Pavan Chilukuri

Thank you for the suggestion, I've edited my post. 👍