Lifting the state up - Props Uncaught TypeError: Cannot read properties of undefined (reading 'map')

Hi Guys,

when I try to lift the state from Counters to App and I save i see the following error in the dev tool:
Uncaught TypeError: Cannot read properties of undefined (reading ‘map’)

It looks like my properties from Counters component in the App class is empty (I have tried to log it in the console unsuccessfully). I tried to reverse the change and everything works fine.

Please find below my App Class:
import NavBar from ‘./components/navbar’;

import ‘./App.css’;

import Counters from ‘./components/counters’;

import React, { Component } from ‘react’;

class App extends Component {

state = {

counters: [

  { id: 1, value: 1 },

  { id: 2, value: 0 },

  { id: 3, value: 0 },

  { id: 4, value: 1 },

],

};

handleDelete = (counterId) => {

// console.log("Delete button clicked", 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/>

<main className='container'>

  <Counters

  counters = {this.state.counters}

  onReset = {this.handleReset}

  onIncrement = {this.handleIncrement}

  onDelete = {this.handleDelete}

  />

</main>

</React.Fragment>

);}

}

export default App;

Here my Counters class:
import React, { Component } from “react”;

import Counter from “./counter”;

class Counters extends Component {

render() {

return (

  <div>

    <button

      onClick={this.props.onReset}

      className="btn btn-primary btn-sm m-2"

    >

      Resets

    </button>

    {this.props.counters.map((counter) => (

      <Counter

        key={counter.id}

        onDelete={this.props.onDelete}

        counter={counter}

        onIncrement={this.props.onIncrement}

      />

    ))}

  </div>

);

}

}

export default Counters;

Please help me understand how can I have the “this.props.counters.map” to not fail

Could you also include your Counter component?

Here the Counter component:
import React, { Component } from “react”;

class Counter extends Component {

render() {

return (

  <div>

    <span style={{ fontSize: 15 }} className={this.getBadgeClasses()}>

      {this.formatCount()}

    </span>

    <button

      onClick={() => this.props.onIncrement(this.props.counter)}

      className="btn btn-secondary btn-sm"

    >

      Increment!

    </button>

    <button

      onClick={() => this.props.onDelete(this.props.counter.id)}

      className="btn btn-danger btn-sm m-2"

    >

      Delete

    </button>

  </div>

);

}

// renderTags() {

// if (this.state.tags.length === 0) return

There are no tags!

;

// return (

//

    // {this.state.tags.map((tag) => (

    //

  • {tag}
  • // ))}

    //

// );

// }

getBadgeClasses() {

let classes = "badge m-2 badge-";

classes += this.props.counter.value === 0 ? "warning" : "primary";

return classes;

}

formatCount() {

const { value } = this.props.counter;

return value === 0 ? "Zero" : value;

}

}

export default Counter;

Strange. I tried your code and I’m not seeing any errors! It seems to work. I don’t import NavBar and App.css because I don’t have those, but otherwise I think it’s mostly the same. Here are the three files:

App.js

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

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

  handleDelete = (counterId) => {
    // console.log("Delete button clicked", 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>
        <main className='container'>
          <Counters
            counters={this.state.counters}
            onReset={this.handleReset}
            onIncrement={this.handleIncrement}
            onDelete={this.handleDelete}
          />
        </main>
      </React.Fragment>
    )
  }
}

export default App

counters.js

import React, { Component } from 'react'
import Counter from './counter'

class Counters extends Component {
  render () {
    return (
      <div>
        <button
          onClick={this.props.onReset}
          className='btn btn-primary btn-sm m-2'
        >
          Resets
        </button>
        {this.props.counters.map((counter) => (
          <Counter
            key={counter.id}
            onDelete={this.props.onDelete}
            counter={counter}
            onIncrement={this.props.onIncrement}
          />
        ))}
      </div>
    )
  }
}
export default Counters

counter.js

import React, { Component } from 'react'

class Counter extends Component {
  render () {
    return (
      <div>
        <span style={{ fontSize: 15 }} className={this.getBadgeClasses()}>
          {this.formatCount()}
        </span>
        <button
          onClick={() => this.props.onIncrement(this.props.counter)}
          className='btn btn-secondary btn-sm'
        >
          Increment!
        </button>
        <button
          onClick={() => this.props.onDelete(this.props.counter.id)}
          className='btn btn-danger btn-sm m-2'
        >
          Delete
        </button>
      </div>
    )
  }

  getBadgeClasses () {
    let classes = 'badge m-2 badge-'
    classes += this.props.counter.value === 0 ? 'warning' : 'primary'
    return classes
  }

  formatCount () {
    const { value } = this.props.counter
    return value === 0 ? 'Zero' : value
  }
}

export default Counter

[quote=“eelsholz, post:4, topic:11806”]

import React, { Component } from 'react'
import Counter from './counter'

[/quote

The error is because you omitted to include the counters={this.state.counters} as a prop the counters component on your App.js … Please comment if you need further clarification.

you can read the full article here Solve: Can Not Read Properties of Undefined Reading Map in React JS