J'utilise la table de réaction ( https://github.com/react-tools/ react-table ) pour afficher un tableau des dépenses. Dans une colonne, il devrait y avoir un bouton pour «approuver» la dépense. Ceci est traité comme ceci:
class ExpensePendingAdmin extends Component { constructor(props) { super(props); this.state = {}; } componentDidMount() { fetch(`${apiRoot}expenses_pending`, { method: "GET", headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: `Token ${this.props.auth.token}` } }) .then(response => response.json()) .then(data => { console.log(data); this.setState({ expenses: data }); }); } approveExpense = id => { fetch(`${apiRoot}expenses_pending/`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: `Token ${this.props.auth.token}` }, body: JSON.stringify({ id: id }) }).then(res => { if (res.status === 200) { this.setState({ issues: this.state.expenses.filter(expense => expense.id != id) }); } else { console.log("Error"); } }); }; render() { const columns = [ { Header: "Description", accessor: "description" }, { Header: "Logged At", id: "loggedAt", accessor: d => moment(d.expense_incur_datetime).format("HH:mm - ddd d/M/YYYY") }, { Header: "Amount", accessor: d => `£${d.amount}`, id: "amount" }, { Header: "Approve", accessor: d => { return <button onClick={this.approveExpense(d.id)}>Approve</button>; }, id: "approved" }, { Header: "Paid", accessor: d => { console.log(d); return d.is_unpaid ? "No" : "Yes"; }, id: "paid" } ]; return ( <div className="container-fluid"> {this.state.expenses ? ( <> <div className="row"> <div className="col text-center"> <h2>Pending Expenses</h2> </div> </div> <div className="row"> <div className="col"> <ReactTable data={this.state.expenses} columns={columns} minRows="0" minWidth="50" showPagination={false} /> </div> </div> </> ) : ( "LOADING" )} </div> ); } }
Où la fonction approveExpense est définie comme:
approveExpense = id => { fetch(`${apiRoot}expenses_pending/`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: `Token ${this.props.auth.token}` }, body: JSON.stringify({ id: id }) }).then(res => { if (res.status === 200) { this.setState({ issues: this.state.expenses.filter(expense => expense.id != id) }); } else { console.log("Error"); } }); };
Curieusement, cependant, lorsque la page se charge se comporte comme si tous ces boutons étaient pressés à plusieurs reprises, plusieurs fois par seconde (jusqu'à ce que les fans commencent à devenir fous et que j'arrête le serveur de réaction).
Est-ce que je fais quelque chose de stupide?
Classe complète:
const columns = [ { Header: "Description", accessor: "description" }, { Header: "Approve", accessor: d => { return <button onClick={this.approveExpense(d.id)}>Approve</button>; }, id: "approved" } ];
4 Réponses :
Les méthodes des gestionnaires d'événements dans JSX ne nécessitent pas de parenthèses, si vous souhaitez transmettre un paramètre, il suffit de l'envelopper dans une fonction:
onClick={() => this.approveExpense(d.id)}
Le problème avec votre code est que vous passez le gestionnaire d'événements de la mauvaise manière:
return <button onClick={(e) => {this.approveExpense(d.id)}}>Approve</button>;
en utilisant directement this.approveExpense (d.id) dans votre code JSX que vous dites javascript pour exécuter cette fonction dès que l'interpréteur la lit. Au lieu de cela, vous devez proxy l'exécution de la fonction sur le clic, comme ceci:
return <button onClick={this.approveExpense(d.id)}>Approve</button>;
Pour des explications plus détaillées sur la façon de passer la fonction aux composants dans React, vous pouvez vérifier https://reactjs.org/docs/faq-functions.html
p >
ce n'est pas un problème de liaison car approveExpense
est déclaré à l'aide d'une fonction de flèche. Vous liez des fonctions, pas des événements.
Merci d'avoir signalé cela, mon erreur en écrivant la réponse
Toutes les autres réponses sont correctes, mais vous pouvez également améliorer la syntaxe de votre appel de fonction en faisant de votre fonction plusieurs jeux de paramètres:
accessor: d => <button onClick={this.approveExpense(d.id)}>Approve</button>;
Et puis en définissant le rendu de votre accesseur comme ceci:
approveExpense = id => ev => {
La fonction: this.approveExpense (d.id)
renverra une autre fonction capable de recevoir un autre paramètre (ici, les noms d'événement de clic ev
) et fonctionnera comme un charme
Dans le code que j'ai donné, this.approveExpense (d.id)
donnera simplement une autre fonction qui peut être appelée dès que l'événement de clic est déclenché, comme expliqué ci-dessus. Regardez la déclaration du paramètre: id => ev => {
Vous devez passer la fonction approveExpense () en tant que fonction de rappel, par exemple, elle ne se déclenchera que lorsque vous cliquerez.
<button onClick={(d) => this.approveExpense(d.id)}>Approve</button>