Estoy aprendiendo los ganchos de React, así que para hacer eso estoy tratando de convertir un componente de clase en un componente funcional, pero todavía obtengo algunos errores.

Aquí está el componente de trabajo original escrito como clase:

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;

Y esta es la versión convertida que usa ganchos.

 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;

La mayor parte funciona bien, pero sigue arrojando un error que dice que el filtro no es una función. Aquí está el mensaje:

TypeError: counters.filter no es una función

5
dadsa 27 feb. 2021 a las 01:03

3 respuestas

La mejor respuesta

El principal culpable parece ser la forma en que está actualizando su estado, que es así:

setCounters({ counterss });

Esto realmente establecerá su estado counters en un objeto con la propiedad counterss, por lo que su estado contendrá lo siguiente:

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

El error exacto que se lanza se refiere al hecho de que está intentando llamar a .filter en un objeto en lugar de una matriz. Para solucionar este problema, simplemente debe actualizar su estado de esta manera:

setCounters(counterss);
3
etarhan 26 feb. 2021 a las 22:19
setCounters({ counterss })

Debe ser

setCounters(counterss)
3
Ben West 26 feb. 2021 a las 22:11

Lanza un error porque estableciste el nuevo estado como un objeto setCounters({ counterss });. Pero quieres una matriz: setCounters(counterss);. De esta forma, no arrojará un error la segunda vez que se llame a setCounters.

3
Szabó Sebestyén 26 feb. 2021 a las 22:11