How do I make page refresh or reender content in page after I click submit button? I've trying to put window.location.reload()
(I know that not the React way, this.forceUpdate()
have same result) in submit functions(closeTicket()
, openTicketSubmit()
) but POST request don't get response
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;
How do I make page refresh or reender content in page after I click submit button? I've trying to put window.location.reload()
(I know that not the React way, this.forceUpdate()
have same result) in submit functions(closeTicket()
, openTicketSubmit()
) but POST request don't get response
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;
Share
Improve this question
edited Feb 5, 2020 at 18:16
johannchopin
14.8k11 gold badges62 silver badges119 bronze badges
asked Feb 5, 2020 at 18:13
MiXProjecTMiXProjecT
551 gold badge1 silver badge4 bronze badges
5
|
7 Answers
Reset to default 4A simple way to re-render would be to change the state variable on the submission of the Axios request causing the component to re-render automatically. Example:
axios({...}).then(resp => {
this.setState({message_body:'',send_to_number:''}); // will cause to re-render
})
You can make the component re-render by updating its state
( after the 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();
})
};
React will rerender components once the state changes, which means that what you need is to change the state once the submit button is clicked. Since the submit button is inside the PersonList component and you also want to reload PersonList, you want to change the state of PersonList when the submit button is clicked.
Here is what you might want to do: 1) add a 'reload' state to PersonList, defaulting it to false. This will tell the component if you need to reload or not. 2) pass a function that sets the state of PersonList's reload value into the child component, in this case CardConversion. something like this.setState({reload:!this.state.reload}) should do. 3) when you finish handling what you need to handle within CardConversion, call your passed function to set the parent's state value, and the whole component should reload.
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)}
/>
and on CardConversation
const handleClick = useCallback(() => {
getPhoneNumberOpenTickets(person);
this.props.reloadParent();
},
in opentickets.js
create a function updatePeople and in that function call this.getPeopleData();
eg
updatePeople = () =>{
this.getPeopleData();
}
then in
return this.state.people.map(person => (
<CardConversation
person={person}
closeTicket={closeTicket}
openTicketsSubmit={openTicketsSubmit}
getPhoneNumberOpenTickets={getPhoneNumberOpenTickets}
openTicketsReply={openTicketsReply}
refreshPeople = {this.updatePeople}
/>
));
in cardConversion.jsx
when you click the close button or whichever button gets you back to openTickets, put the callback function
this.props.refreshPeople();
because you have componentDidMount, everytime you call whatever is in componentDidMount, it will update the information and re render it
First of all, regarding you are not getting any data issue, you can check axios, and how they use post:
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
// where you can setState here
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Mainly axios are handling the data asynchronously. By that, once you call the api, React will executes next line of code.
For more discussion of how to force update the component, you can check this post: Can you force a React component to rerender without calling setState?, which explain how to update component very well.
As far as I can see, what you're trying to do is reload the people list. If that's the case, you can solve it in two ways:
- In both
axios
API calls, add.then()
block and callthis.getPeopleData()
. - Instead of re-fetching people's data, you get the added/deleted post data and update state in the
.then()
block withsetState()
.
I suggest you to adopt Option 2, because fetching the list again will require more time for you to get the refreshed list.
Either way, just adding this.forceUpdate()
to your .then()
block will not give you the updated list. It won't do anything actually to the UI. (though it makes it re-render)
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}
/>
));
}
}
ticket.closed = true
? – James Commented Feb 5, 2020 at 18:20closed: false
inthis.state
and dothen(() => { this.setState({ closed: true}); }
after axios and deletee.preventDefault()
– MiXProjecT Commented Feb 5, 2020 at 18:46setState
in there – James Commented Feb 5, 2020 at 19:03