1
votes

React setState fonction non atteinte donc ne fonctionne pas

J'essayais de compter les tâches terminées et la logique devrait être correcte je crois, mais il semble que this.setState ({}) ne répond pas / atteint du tout, il ne fait rien aux données 'qtySelected' dans this.state ({}) puisque console.log ('ts') n'a pas eu de résultat dans la console. Tout le monde sait pourquoi, c'est peut-être un problème de cycle de vie de réaction?

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>
        )
    }
}


0 commentaires

3 Réponses :


2
votes

Vous n'appelez la fonction this.countSelected nulle part. Dans tous les cas, les données que vous pouvez calculer directement à partir de l'état actuel ne doivent pas être stockées dans l'état.

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>
    );
  }
}


2 commentaires

merci pour la solution, cela a fonctionné. Mais vous avez dit «ne devrait pas», pourquoi? C'est juste une mauvaise pratique mais fonctionne toujours, ou c'est tout simplement faux et ne fonctionnera pas (j'ai essayé de garder l'état `` qtySelected '' comme ce que Luke Storry a suggéré mais cela ne fonctionnait que lorsqu'il était chargé et ne serait pas mis à jour lorsque j'ai coché d'autres cases, c'est cela a été causé par l'ajout de ce nouvel état supplémentaire qtySeleceted?)


C'est juste une mauvaise pratique - cela fonctionnera toujours, mais chaque fois que vous utiliserez setState , le composant sera de nouveau rendu - si vous créez simplement un nouvel état basé uniquement sur l'ancien état, vous n'avez pas besoin pour le rendre deux fois - stockez simplement la valeur calculée dans une variable comme dans cette réponse



1
votes

Rien n'exécute cette fonction.countSelected. Supprimez donc la fonction ou rendez-la externe à componentDidMount et appelez-la depuis componentDidMount.


0 commentaires

2
votes

En fait, vous n'exécutez rien dans le componentDidMount - vous définissez simplement une nouvelle fonction this.countSelected .

En utilisant également la version de rappel de setState est la meilleure pratique a> lorsque vous utilisez une valeur d'état précédente pour mettre à jour l'état.


Dans l'ensemble, vous pouvez l'utiliser comme nouveau componentDidMount et cela devrait fonctionner comme prévu:

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

Alternativement, vous devriez probablement simplement utiliser cette valeur calculée directement au lieu de forcer un deuxième rendu, car il n'a pas vraiment besoin d'être une variable d'état séparée .

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


2 commentaires

merci pour votre explication, mais la première façon a toujours un problème: cela n'a fonctionné qu'une seule fois lorsque vous venez de charger la page, et après si vous cochez d'autres cases, le numéro ne se met pas à jour et reste à '1' sélectionné. Le second fonctionne sans problème cependant.


Oui, c'est la définition exacte de componentDidMount . Il fonctionnera une fois, sur le montage. Si vous voulez qu'il exécute tous les rendus, placez-le dans la fonction de rendu.