So my problem is that i update my state but when i try to use it to approuve my payment the OrderUrl is empty i undestard that setState is asynchrone but how can i avoid this case and update my state immediately.
i have this problem like in two or three page in my website, and i already did some searches some dudes say that i can use useEeffect to update my state by i can’t use it in my case.
import React, {useRef, useState, useEffect, useContext} from "react"; const paimentValidation = () => { **// ***************This is my state ConfirmUrl******************* ** const [orderUrl, setorderUrl] = useState(""); const [confirmUrl, setconfirmUrl] = useState(""); function getOrder() { console.log("order url", orderUrl); var ddata = {arrival: arrival, departure: departure, propertyId: id, hosting_capacity: nbrVoyager}; console.log('ddata', ddata); return fetch(orderUrl, { method: "POST", body: JSON.stringify(ddata), headers: { 'content-type': 'application/json', 'Accept': 'application/json', 'Authorization': localStorage.getItem('access_token') ? localStorage.getItem('access_token') : '' } }).then(function (res) { return res.json(); }).then(function (data) { localStorage.setItem('data', data); console.log("LOG CONFIRM URL", data.confirmUrl); ** ******************** // HERE I UPDATE MY STATE************************ ** setconfirmUrl(data.confirmUrl); console.log("confirm url", confirmUrl); return data.orderID; }) } function approuve () { ** **************AND HERE MY STATE confirmUrl is empty so i get an error with paypal paiment********************** ** **console.log('CONFIRM URL', confirmUrl);** useEffect(() => alert(confirmUrl), [confirmUrl]); return fetch(confirmUrl, { headers: { 'content-type': 'application/json', 'Accept': 'application/json', 'Authorization': localStorage.getItem('access_token') ? localStorage.getItem('access_token') : '' } }).then(function (res) { return res.json(); }).then(function (data) { router.push("paymentsuccess"); }) } return ( <LoadingOverlay active={orderUrl == ""} spinner text='Loading ...' > <h2 className={styles.titles}>Payer avec</h2> {orderUrl != "" ? ( <PayPalScriptProvider options={{ "client-id": "AYz2CwrBi8Tu5wdVqsd9IIs3ZdfN0C7cIkA0gczx_AquHaVQQIQJT2M4Neghd04Kje2At62p2ked1-Bu", currency: "EUR", commit: true }}> <PayPalButtons createOrder={getOrder} onApprove={approuve} /> </PayPalScriptProvider>) : (<br/>)} </div> </div> </div> </LoadingOverlay> ); }; export default paimentValidation;
Advertisement
Answer
You can use your onApprove
handler in the PayPalButtons
component to set some state and then call your approuve
function from inside a useEffect hook that depends on it:
const paimentValidation = () => { const [orderUrl, setorderUrl] = useState(""); const [confirmUrl, setconfirmUrl] = useState(""); const [approved, setApproved] = useState(false); useEffect(() => { if(confirmURL && approved) { // we have the confirmation url and approval from the paypal buttons approuve(); } }, [approved, confirmUrl]); // runs whenever the approved OR confirmUrl state changes ... <PayPalButtons createOrder={getOrder} onApprove={() => setApproved(true)} // the button now just sets the state flag, which will trigger the useEffect on the next render /> ... };