Реагировать: перерисовать комп onet после нажатия кнопки - PullRequest
2 голосов
/ 05 февраля 2020

Как мне сделать страницу refre sh или обновить содержание на странице после того, как я нажму кнопку отправки? Я пытаюсь поместить window.location.reload() (я знаю, что не способ React, this.forceUpdate() имеет тот же результат) в функции отправки (closeTicket(), openTicketSubmit()), но запрос POST не получает ответ

OpenTickets. js

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

CardConversation.jsx

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;

Ответы [ 6 ]

1 голос
/ 05 февраля 2020

React перезапустит компоненты после изменения состояния, а это означает, что вам нужно изменить состояние после нажатия кнопки отправки. Так как кнопка отправки находится внутри компонента PersonList, и вы также хотите перезагрузить PersonList, вы хотите изменить состояние PersonList при нажатии кнопки отправки.

Вот что вы, возможно, захотите сделать: 1) добавить состояние «перезагрузки» в PersonList, по умолчанию присвоив ему значение false. Это скажет компоненту, если вам нужно перезагрузить или нет. 2) передать функцию, которая устанавливает состояние значения перезагрузки PersonList в дочерний компонент, в данном случае CardConversion. что-то вроде this.setState ({reload:! this.state.reload}) должно делать. 3) когда вы закончите sh обработку того, что вам нужно обработать в CardConversion, вызовите переданную функцию, чтобы установить значение состояния родителя, и весь компонент должен перезагрузиться.

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

и на CardConversation

const handleClick = useCallback(() => {
  getPhoneNumberOpenTickets(person);
  this.props.reloadParent();
},
1 голос
/ 05 февраля 2020

Простой способ повторного рендеринга - изменить переменную состояния при отправке запроса Ax ios, в результате чего компонент автоматически выполнит повторный рендеринг. Пример:

axios({...}).then(resp => {
 this.setState({message_body:'',send_to_number:''}); // will cause to re-render
})
1 голос
/ 05 февраля 2020

Вы можете выполнить повторную визуализацию компонента, обновив его state (после 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();
  })
};
0 голосов
/ 06 февраля 2020

CardConversatio.jsx

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;

OpenTickets. js

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}
            />
        ));
    }
}
0 голосов
/ 05 февраля 2020

Насколько я понимаю, вы пытаетесь перезагрузить список людей. Если это так, вы можете решить ее двумя способами:

  1. В обоих axios вызовах API добавьте .then() block и вызовите this.getPeopleData().
  2. Вместо повторного вызова. - при выборке данных о людях вы получаете добавленные / удаленные данные постов и состояние обновления в блоке .then() с помощью setState().

. Я предлагаю вам принять вариант 2, поскольку повторная выборка списка будет требуется больше времени для получения обновленного списка.

В любом случае, просто добавив this.forceUpdate() в свой блок .then(), вы не получите обновленный список. Это на самом деле ничего не сделает с пользовательским интерфейсом. (хотя это заставляет это повторно сделать)

0 голосов
/ 05 февраля 2020

Прежде всего, если у вас нет проблем с данными, вы можете проверить ax ios и как они используют почту:

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    // where you can setState here
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

Преимущественно ax ios обрабатывают данные асинхронно. При этом, как только вы вызовете API, React выполнит следующую строку кода.

Для более подробного обсуждения того, как принудительно обновить компонент, вы можете проверить это сообщение: Можете ли вы заставить компонент React перерисовываться без вызова setState? , который объясняет, как очень хорошо обновить компонент .

...