React setState function not reached thus not working

Viewed 59

I was trying to count the completed tasks, and the logic should be right I believe, but seems the this.setState({}) is not responding/reached at all, it's not doing anything to the data 'qtySelected' in the this.state({}) since the console.log('ts') didn't have a result in the console. Anyone knows why, maybe it's some react lifecycle issue?

export class Main extends Component {
    constructor(pros) {
        super(pros)
        this.state = {
            tasks: [
                {
                    id: 1,
                    content: "Sara's doctor and vaccine",
                    due: '2020-08-29',
                    completed: false
                },
                {
                    id: 2,
                    content: "Trash bags / facial masks / child allowance",
                    due: '2020-08-28',
                    completed: false
                },
                {
                    id: 3,
                    content: "Apply for Portugal nationality",
                    due: '2020-09-31',
                    completed: false
                },
                {
                    id: 4,
                    content: "My registeration card",
                    due: '2020-09-28',
                    completed: false
                },
                {
                    id: 5,
                    content: "contact ADEM",
                    due: '2020-12-31',
                    completed: false
                },
                {
                    id: 6,
                    content: "Pay loan",
                    due: '2020-09-03',
                    completed: true
                }
            ],
            qtySelected: 0
        }

    }


    componentDidMount() {    
        this.countSelected = () => {
            console.log('ts')
            let tasksCompleted = this.state.tasks.filter(task => {
                return task.completed === true
            })
            this.setState({
                qtySelected: tasksCompleted.length
            })
        }    
    }

    render() {
        return (
            <div>
                <table>
                    <tfoot>
                        <tr>
                            <td style={{ whiteSpace: "nowrap" }}>{this.state.qtySelected} selected</td>
                        </tr>
                    </tfoot>
                </table>
            </div>
        )
    }
}
3 Answers

You're not calling the this.countSelected function anywhere. Either way, data you can compute directly from the current state should not be stored in the state.

export class Main extends Component {
  constructor(props) {
    super(props);
    this.state = {
      tasks: [
        // ...
      ],
    };
  }

  render() {
    const selectedCount = this.state.tasks.filter((task) => task.completed).length;
    return (
      <div>
        <table>
          <tfoot>
            <tr>
              <td style={{ whiteSpace: "nowrap" }}>{selectedCount} selected</td>
            </tr>
          </tfoot>
        </table>
      </div>
    );
  }
}

You are not actually running anything in the componentDidMount - you are just defining a new function this.countSelected.

Also using the callback version of setState is best practise when you are using a previous state value to update state.


All together, you can use this as your new componentDidMount and it should work as expected:

componentDidMount() {    
    this.setState(state => ({
        qtySelected: state.tasks.filter(task => task.completed).length
    }))
}

Alternatively, you probably should just use this computed value directly instead of forcing a second re-render, as it doesn't really need to be a separate state variable.

<td style={{ whiteSpace: "nowrap" }}>
  {this.state.tasks.filter(task => task.completed).length} selected
</td>

Nothing is executing this.countSelected function. So remove the function or make it extern to componentDidMount and call it from componentDidMount.

Related