Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert class component to functional component in React

I'm learning React hooks so in order to do that I'm trying to convert a class component to a functional component but I still get some errors.

Here is the original working component written as a class:

import React, { Component } from 'react';
import NavBar from './components/navbar';
import Counters from './components/counters';

class App extends Component {
  state = {
    counters: [
      { id: 0, value: 5 },
      { id: 1, value: 1 },
      { id: 2, value: 2 },
    ],
  };

  handleDelete = (counterId) => {
    const counters = this.state.counters.filter((c) => c.id !== counterId);
    this.setState({ counters });
  };

  handleReset = () => {
    const counters = this.state.counters.map((c) => {
      c.value = 0;
      return c;
    });
    this.setState({ counters });
  };

  handleIncrement = (counter) => {
    const counters = [...this.state.counters];
    const index = counters.indexOf(counter);
    counters[index] = { ...counter };
    counters[index].value++;
    this.setState({ counters });
  };
  render() {
    return (
      <React.Fragment>
        <NavBar
          totalCounters={this.state.counters.filter((c) => c.value > 0).length}
        />
        <main className='container'>
          <Counters
            counters={this.state.counters}
            onReset={this.handleReset}
            onDelete={this.handleDelete}
            onIncrement={this.handleIncrement}
          />
        </main>
      </React.Fragment>
    );
  }
}

export default App;

And this is the converted version which uses hooks.

 import React, { useState } from 'react';
    import NavBar from './components/navbar';
    import Counters from './components/counters';
    
    const App = () => {
      const [counters, setCounters] = useState([
        { id: 0, value: 5 },
        { id: 1, value: 1 },
        { id: 2, value: 2 },
      ]);
    
      const handleDelete = (counterId) => {
        const counterss = counters.filter((c) => c.id !== counterId);
        setCounters({ counterss });
      };
    
      const handleReset = () => {
        const counterss = counters.map((c) => {
          c.value = 0;
          return c;
        });
        setCounters({ counterss });
      };
    
      const handleIncrement = (counter) => {
        const counterss = [...counters];
        const index = counterss.indexOf(counter);
        counterss[index] = { ...counter };
        counterss[index].value++;
        setCounters({ counterss });
      };
    
      return (
        <React.Fragment>
          <NavBar totalCounters={counters.filter((c) => c.value > 0).length} />
          <main className='container'>
            <Counters
              counters={counters}
              onReset={handleReset}
              onDelete={handleDelete}
              onIncrement={handleIncrement}
            />
          </main>
        </React.Fragment>
      );
    };
    
    export default App;

Most of it works fine but it keeps throwing an error saying that filter is not a function. Here it is the message:

TypeError: counters.filter is not a function

like image 300
dadsa Avatar asked Feb 26 '21 22:02

dadsa


People also ask

How do you convert a class component to a functional component React?

Converting to the functional component:Removed the class keyword and directly exported our component. Removed use of constructor and super. Changed how we were setting the state and used useState hook instead. Removed componentDidMount() and used useEffect hook instead.

Can we import class component in functional component?

You cannot use a class component with a functional component inside of it. Because they work different, for example. Inside a class based component you have the render method that returns an html. And in a functional component the return of the function is and html.

Can we pass props from class component to functional component?

Of course, you can still pass props from parent to child with functional components but the big difference is that you'll need to declare them in your functional component callback just as you would with any other type of function. Now you can access those props.

How to make use of State in react functional components?

You can convert this entire class into a functional React component using Hooks: Here, you have introduced the useState Hook. It allows you to make use of state in React functional components. With the useState () Hook, you can use state in this functional component. It uses a similar syntax with a destructuring assignment for arrays.

What is the difference between functional components and react functions?

Function components are far less verbose, and require less boilerplate. They're (in my opinion) a bit more flexible with hooks and custom hooks, and they are (usually) a bit more performant. Note: in the examples below, I've shown how to import `React` and `Component`.

How do I convert a class-based component to a functional component?

If, for example, you had two or more input fields for userName, firstName, and lastName, then you would have a class-based component with three state properties: To convert this class to a functional component with Hooks, you will have to take a somewhat unconventional route.

What is the difference between a class component and function component?

The class component needs to extend the React Component class, and must specify a render method. Whereas the function component is simply a function, and the render method is simply the return value of the function. Why convert a class component to a function component


1 Answers

The main culprit appears to be the way you are updating your state, which is like this:

setCounters({ counterss });

This will actually set your counters state to an object with the property counterss, so your state will contain the following:

{ counterss: [/* rest of the array */] }

The exact error being thrown is referring to the fact that you are attempting to call .filter on an object instead of an array. To fix this issue you should simply update your state like this:

setCounters(counterss);
like image 101
etarhan Avatar answered Oct 21 '22 23:10

etarhan