Comment actualiser la page ou renvoyer le contenu de la page après avoir cliqué sur le bouton Soumettre? J'ai essayé de mettre window.location.reload()
(je sais que ce n'est pas la manière React, this.forceUpdate()
ont le même résultat) dans les fonctions de soumission ( closeTicket()
, openTicketSubmit()
) mais la demande POST ne reçoit pas réponse
OpenTickets.js
import React, { useCallback, useEffect, useState } from "react"; import { Button, Accordion, Card, Form, Row, Col } from "react-bootstrap"; import axios from "axios"; const CardConversation = ({ person, closeTicket, openTicketsSubmit, getPhoneNumberOpenTickets, openTicketsReply, }) => { const [conversation, setConversation] = useState([]); // Handlers const handleSubmit = useCallback( e => { openTicketsSubmit(e); }, [openTicketsSubmit] ); const handleCloseTicket = useCallback( e => { closeTicket(e); }, [closeTicket], ); const handleClick = useCallback(() => { getPhoneNumberOpenTickets(person); }, [person, getPhoneNumberOpenTickets]); const handleChange = useCallback( e => { openTicketsReply(e); }, [openTicketsReply] ); // Methods const fetchConversation = useCallback(async () => { try { const { data } = await axios.get( "/getconvfornum?customer_number=" + person.slice(1) ); setConversation(data); } catch (e) { console.log("error: ", e); } }, [person, conversation]); // Effects useEffect(() => { fetchConversation(person) }, [person]); return ( <Accordion defaultActiveKey="0"> <Card> <Card.Header> <Accordion.Toggle as={Button} variant="button" eventKey="0"> Conversation {person.indexOf(person)+1+ ' '} Phone number: {person} </Accordion.Toggle> </Card.Header> <Accordion.Collapse eventKey="0"> <Card.Body> {conversation.map(message => ( <div> <p>{message.from}</p> <p>{message.body}</p> </div> ))} <Form onSubmit={handleSubmit}> <br /> <Form.Group as={Row} controlId="formPlaintextPassword"> <Col sm="10"> <Form.Control type="text" placeholder="Reply" name="message_body" onChange={handleChange} /> </Col> <Button type={"submit"} onClick={handleClick} column sm="2"> Reply </Button> </Form.Group> </Form> <Form onSubmit={handleCloseTicket}> <Form.Group> <Col sm="11"> <Button type={"submit"} onClick={handleClick} column sm="4"> Close Ticket </Button> </Col> </Form.Group> </Form> </Card.Body> </Accordion.Collapse> </Card> <br /> </Accordion> ); }; export default CardConversation;
CardConversation.jsx
import React from "react"; import axios from "axios"; import CardConversation from './CardConversation.jsx'; export default class PersonList extends React.Component { constructor(props) { super(props); this.state = { people: [], send_to_number: "", message_body: "" }; this.closeTicket = this.closeTicket.bind(this); this.openTicketsReply = this.openTicketsReply.bind(this); this.openTicketsSubmit = this.openTicketsSubmit.bind(this); this.getPhoneNumberOpenTickets = this.getPhoneNumberOpenTickets.bind(this); } openTicketsReply = async e => { this.setState({ [e.target.name]: e.target.value }); }; getPhoneNumberOpenTickets = async e => { this.setState({ send_to_number: e }); }; openTicketsSubmit = async e => { e.preventDefault(); const formData = new FormData(); formData.set("send_to_number", this.state.send_to_number.slice(1)); formData.set("message_body", this.state.message_body); axios({ method: "post", url: "/outgoingsms", data: formData, headers: { "Content-Type": "multipart/form-data" } }) }; closeTicket = async e => { e.preventDefault(); const formData = new FormData(); formData.set("customernum", this.state.send_to_number.slice(1)); axios({ method: "post", url: "/closeticket", data: formData, headers: { "Content-Type": "multipart/form-data" } }) }; componentDidMount() { this.getPeopleData(); } getPeopleData = async () => { try { const { data } = await axios.get(`/getongoing?limit=10`); this.setState({ people: data }); } catch (e) { console.log("error: ", e); } }; render() { const { closeTicket, openTicketsSubmit, getPhoneNumberOpenTickets, openTicketsReply } = this; return this.state.people.map(person => ( <CardConversation person={person} closeTicket={closeTicket} openTicketsSubmit={openTicketsSubmit} getPhoneNumberOpenTickets={getPhoneNumberOpenTickets} openTicketsReply={openTicketsReply} /> )); } }
7 Réponses :
Vous pouvez rendre le composant re-rendu en mettant à jour son state
(après le POST):
closeTicket = async e => { e.preventDefault(); const formData = new FormData(); formData.set("customernum", this.state.send_to_number.slice(1)); axios({ method: "post", url: "/closeticket", data: formData, headers: { "Content-Type": "multipart/form-data" } }) .then(() => { this.setState({ /* */ }) // or // this.forceUpdate(); }) };
j'ajoute closed: false
dans this.state
et fais then(() => { this.setState({ closed: true}); })
page n'est pas rendue
la mise à jour de l'état actualisera le composant, supprimez e.preventDefault();
de openTicketsSubmit
si vous voulez que la page se rafraîchisse, mais je ne le recommanderais pas, essayez de mettre à jour l'état dans openTicketsSubmit
comme dans closeTicket
je supprime 'e.preventDefault ();' mais ce n'est même plus l'envoi de demande de publication
Un moyen simple de refaire le rendu serait de changer la variable d'état lors de la soumission de la requête Axios, ce qui entraînerait le re-rendu automatique du composant. Exemple:
axios({...}).then(resp => { this.setState({message_body:'',send_to_number:''}); // will cause to re-render })
Tout d'abord, si vous ne rencontrez aucun problème de données, vous pouvez vérifier axios et comment ils utilisent la publication:
axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { // where you can setState here console.log(response); }) .catch(function (error) { console.log(error); });
Les axios traitent principalement les données de manière asynchrone. Par cela, une fois que vous appelez l'API, React exécutera la prochaine ligne de code.
Pour plus de discussion sur la façon de forcer la mise à jour du composant, vous pouvez consulter cet article: Pouvez-vous forcer un composant React à se réémettre sans appeler setState? , qui expliquent très bien comment mettre à jour le composant.
Pour autant que je sache, ce que vous essayez de faire, c'est de recharger la liste des personnes. Si tel est le cas, vous pouvez le résoudre de deux manières:
axios
, ajoutez le bloc .then()
et appelez this.getPeopleData()
..then()
bloc avec setState()
.Je vous suggère d'adopter l'option 2, car la récupération de la liste nécessitera plus de temps pour obtenir la liste actualisée.
Quoi qu'il en soit, ajouter simplement this.forceUpdate()
à votre bloc .then()
ne vous donnera pas la liste mise à jour. Cela ne fera rien pour l'interface utilisateur. (bien que cela le rende à nouveau)
React rendra les composants une fois que l'état aura changé, ce qui signifie que ce dont vous avez besoin est de changer l'état une fois que vous avez cliqué sur le bouton d'envoi. Étant donné que le bouton d'envoi se trouve à l'intérieur du composant PersonList et que vous souhaitez également recharger PersonList, vous souhaitez modifier l'état de PersonList lorsque vous cliquez sur le bouton d'envoi.
Voici ce que vous voudrez peut-être faire: 1) ajouter un état «recharger» à PersonList, en le définissant par défaut sur false. Cela indiquera au composant si vous devez recharger ou non. 2) transmettre une fonction qui définit l'état de la valeur de rechargement de PersonList dans le composant enfant, dans ce cas CardConversion. quelque chose comme this.setState ({reload:! this.state.reload}) devrait faire. 3) lorsque vous avez terminé de gérer ce que vous devez gérer dans CardConversion, appelez votre fonction passée pour définir la valeur de l'état du parent, et le composant entier devrait se recharger.
const handleClick = useCallback(() => { getPhoneNumberOpenTickets(person); this.props.reloadParent(); },
et sur CardConversation
this.state = { reload: false ... } ... shouldReload() { this.setState({reload:!this.state.reload}); } ... <CardConversation person={person} closeTicket={closeTicket} openTicketsSubmit={openTicketsSubmit} getPhoneNumberOpenTickets={getPhoneNumberOpenTickets} openTicketsReply={openTicketsReply} reloadParent={this.shouldReload.bind(this)} />
dans const handleClick
dit que this.props.reloadParent();
est une fonction ou une méthode non résolue. J'ai essayé de le réparer mais toujours pas de résultat. voici à quoi ressemble le code en ce moment lien
@mixproject votre lien n'a pas d'exemple fonctionnel mais j'ai essayé de scanner le code rapidement et de voir si je peux voir un problème. Se pourrait-il que vous ne liez pas "this" dans la fonction shouldReload? Vérifiez également les accessoires que vous transmettez en les affichant simplement dans la console: console.log (this.props). Merci d'avance
CardConversatio.jsx
import React from "react"; import axios from "axios"; import CardConversation from './CardConversation.jsx'; export default class PersonList extends React.Component { constructor(props) { super(props); this.state = { people: [], send_to_number: "", message_body: "", closed: false }; this.closeTicket = this.closeTicket.bind(this); this.openTicketsReply = this.openTicketsReply.bind(this); this.openTicketsSubmit = this.openTicketsSubmit.bind(this); this.getPhoneNumberOpenTickets = this.getPhoneNumberOpenTickets.bind(this); this.getPhoneToCloseTicket = this.getPhoneToCloseTicket.bind(this); } openTicketsReply = async e => { e.preventDefault(); this.setState({ message_body: e.target.value }); }; getPhoneNumberOpenTickets = async e => { //e.preventDefault(); this.setState({ send_to_number: e }, async () => await this.openTicketsSubmit()); }; getPhoneToCloseTicket = async e => { this.setState({ send_to_number: e }, async () => this.closeTicket()); }; openTicketsSubmit = async e => { const formData = new FormData(); formData.set("send_to_number", this.state.send_to_number.slice(1)); formData.set("message_body", this.state.message_body); axios({ method: "post", url: "/outgoingsms", data: formData, headers: { "Content-Type": "multipart/form-data" } }).then(resp => { this.setState({ closed: true }); }).catch(error => console.log(error)) }; closeTicket = async e => { const formData = new FormData(); formData.set("customernum", this.state.send_to_number.slice(1)); axios({ method: "post", url: "/closeticket", data: formData, headers: { "Content-Type": "multipart/form-data" } }).then(resp => { this.setState({ closed: true }); }).catch(error => console.log(error)) }; componentDidMount() { this.getPeopleData(); } getPeopleData = async () => { try { const { data } = await axios.get(`/getongoing?limit=10`); this.setState({ people: data }); } catch (e) { console.log("error: ", e); } }; render() { const { closeTicket, getPhoneNumberOpenTickets, openTicketsReply, getPhoneToCloseTicket } = this; return this.state.people.map(person => ( <CardConversation key={person} person={person} closeTicket={closeTicket} getPhoneNumberOpenTickets={getPhoneNumberOpenTickets} openTicketsReply={openTicketsReply} getPhoneToCloseTicket={getPhoneToCloseTicket} /> )); } }
OpenTickets.js
import React, { useCallback, useEffect, useState } from "react"; import { Button, Accordion, Card, Form, Row, Col } from "react-bootstrap"; import axios from "axios"; const CardConversation = ({ person, closeTicket, openTicketsSubmit, getPhoneNumberOpenTickets, openTicketsReply, getPhoneToCloseTicket, }) => { const [conversation, setConversation] = useState([]); const [trigger, fireUpdate] = useState(false); // Handlers const renderConversation = useCallback(() => { return conversation.map(message => ( <div key={message.date.$date + person}> <p>{message.from}</p> <p>{message.body}</p> </div> )); }, [conversation, person]); const fetchConversation = useCallback(async () => { try { const { data } = await axios.get( "/getconvfornum?customer_number=" + person.slice(1) ); setConversation(data); console.log("fetch ", data); } catch (e) { console.log("error: ", e); } }, [person]); const handleClick = useCallback(async () => { await getPhoneNumberOpenTickets(person); setTimeout(() => fetchConversation(person), 500); }, [getPhoneNumberOpenTickets, person, fetchConversation]); const handleClickClose = useCallback(async () => { await getPhoneToCloseTicket(person); }, [person, getPhoneToCloseTicket]); const handleChange = useCallback( e => { openTicketsReply(e); }, [openTicketsReply] ); useEffect(() => { console.log("effect"); fetchConversation(person); }, [fetchConversation, person]); return ( <Accordion defaultActiveKey="0"> <Card> <Card.Header> <Accordion.Toggle as={Button} variant="button" eventKey="0"> Conversation {person.indexOf(person) + 1 + " "} Phone number: {person} </Accordion.Toggle> </Card.Header> <Accordion.Collapse eventKey="0"> <Card.Body> {renderConversation()} <Form> <br /> <Form.Group as={Row} controlId="formPlaintextPassword"> <Col sm="10"> <Form.Control type="text" placeholder="Reply" name="message_body" onChange={handleChange} /> </Col> <Button onClick={handleClick} column sm="2"> Reply </Button> </Form.Group> </Form> <Form> <Form.Group> <Col sm="11"> <Button onClick={handleClickClose} column sm="4"> Close Ticket </Button> </Col> </Form.Group> </Form> </Card.Body> </Accordion.Collapse> </Card> <br /> </Accordion> ); }; export default CardConversation;
dans opentickets.js
créez une fonction updatePeople et dans cette fonction, appelez this.getPeopleData();
par exemple
return this.state.people.map(person => ( <CardConversation person={person} closeTicket={closeTicket} openTicketsSubmit={openTicketsSubmit} getPhoneNumberOpenTickets={getPhoneNumberOpenTickets} openTicketsReply={openTicketsReply} refreshPeople = {this.updatePeople} /> ));
puis dans
updatePeople = () =>{ this.getPeopleData(); }
dans cardConversion.jsx
lorsque vous cliquez sur le bouton de fermeture ou sur n'importe quel bouton qui vous ramène à openTickets, mettez la fonction de rappel
this.props.refreshPeople();
parce que vous avez componentDidMount, chaque fois que vous appelez ce qui se trouve dans componentDidMount, il mettra à jour les informations et les rendra
Vraisemblablement, lorsque vous fermez un ticket, cela entraînera un changement d'état? par exemple
ticket.closed = true
?J'ai essayé mais ça n'aide pas
@MiXProjectT montre ce que vous avez fait?
j'ajoute
closed: false
dansthis.state
et faisthen(() => { this.setState({ closed: true}); }
après axios et supprimee.preventDefault()
@MiXProjectT trop tôt, ajoutez un rappel à votre appel Axios, puis exécutez
setState
là-dedans