2
votes

Réagir: afficher le composant après avoir cliqué sur le bouton

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


5 commentaires

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 dans this.state et fais then(() => { this.setState({ closed: true}); } après axios et supprime e.preventDefault()


@MiXProjectT trop tôt, ajoutez un rappel à votre appel Axios, puis exécutez setState là-dedans


7 Réponses :


2
votes

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


3 commentaires

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



2
votes

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


0 commentaires

0
votes

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.


0 commentaires

0
votes

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:

  1. Dans les deux appels d'API axios , ajoutez le bloc .then() et appelez this.getPeopleData() .
  2. Au lieu de re-récupération des données des gens, vous obtenez la valeur ajoutée / supprimé données post et de l' état de mise à jour dans le .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)


0 commentaires

1
votes

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


2 commentaires

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



0
votes

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;


0 commentaires

1
votes

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


0 commentaires