const LoadingPage = ({merchantId, order}) => {
const router = useRouter();
useEffect(() => {
if (order.status === "merchantAccepted") {
router.push(`/${merchantId}/success`);
}
}, []);
return (
<Column>
Waiting merchant to accept...
</Column>
);
};
export default LoadingPage;
export const getServerSideProps = async (ctx) => {
const {params} = ctx;
const {merchantId} = params;
const merchant = await getMerchant(merchantId);
const order = await getOrders("");
return {
props: {
merchantId,
merchant: merchant,
order
}
};
};
What I am trying to do is waiting for merchant to accept the order which change the status of the order in db. Then I would like to fetch that status which will be use to redirect user to another page. At the moment I am using getServerSideProps but this method only fetch it once and I need to refresh the page. How do I make the API calls without refreshing the page?
Thank you.
There are a couple things working against you here, but it's pretty easy to solve!
The first issue is in your effect. It only runs once instead of any time the order status changes. Super easy to fix by adding a dependency on order.status
:
useEffect(() => {
if (order.status === "merchantAccepted") {
router.push(`/${merchantId}/success`);
}
}, [order.status]);
Now, to get the updated order information, we need to make some bigger changes. The first thing you'll want to do is cache the value of order
in state so you can allow the component to call the API and update the state. The second thing is to pass in a way to update the order status. Combining the change to the effect hook plus those requirements, I came up with this for you:
const LoadingPage = ({ getOrders, merchantId, order: orderProp }) => {
const router = useRouter();
const [order, setOrder] = useState(orderProp);
useEffect(() => {
if (order.status === "merchantAccepted") {
router.push(`/${merchantId}/success`);
}
}, [order.status]);
useEffect(() => {
// skip if merchant already accepted
if (order.status === "merchantAccepted") return;
// keep track of the timeout so we can cancel
let timeout;
// create an internal function to call the API to check for updates
const checkApi = async () => {
const updatedOrder = await getOrders("");
setOrder(updatedOrder);
if (updatedOrder.status !== "merchantAccepted") {
// wait 2 seconds to call again
timeout = setTimeout(checkApi, 2000);
}
}
// make the initial check in 2 seconds
timeout = setTimeout(checkApi, 2000);
// on unmount, make sure we cancel
return () => {
clearTimeout(timeout);
}
}, []); // only execute this effect on mount
return (
<Column>
Waiting merchant to accept...
</Column>
);
};
export default LoadingPage;
export const getServerSideProps = async (ctx) => {
const {params} = ctx;
const {merchantId} = params;
const merchant = await getMerchant(merchantId);
const order = await getOrders("");
return {
props: {
merchantId,
merchant: merchant,
order,
getOrders
}
};
};
I think this will solve it for you. Let me know if you have any questions!