Search code examples
reactjspaypalpaypal-sandboxpaypal-rest-sdk

PayPal React shows extra buttons after changing amount


WITHOUT react-paypal-button-v2 ~~~has an ovehead of 60KB

Similar question here but they suggest react-paypal-button-v2

I'm Trying to make a React PayPal button that changes the billing amount on props change.

I call the following component with props price and every time the price change i would like to re-render the button to update the actual price. WITHOUT react-paypal-button-v2

const PaypalForm = props => {
  let paypalRef = useRef();

  useEffect(() => {      
    window.paypal
      .Buttons({
        createOrder: (data, actions) => {
          return actions.order.create({
            purchase_units: [
              {
                description: "test",
                amount: {
                  currency_code: "USD",
                  value: props.price
                }
              }
            ]
          });
        },
        onApprove: async (data, actions) => {
          const order = await actions.order.capture();
          console.log(order);
        },
        onError: err => {
          setError(err);
          console.error(err);
        }
      })
      .render(paypalRef.current);
  }, [props.price]);

  return (
    <Row className="justify-content-center">
      {error && <div>Uh oh, an error occurred! {error.message}</div>}
      <div ref={paypalRef} />
    </Row>
  );
};

Everything is working except that a new button is created and added in the bottom of old one at each props change. I would like my new button to replace the old one. Without using react-paypal-button-v2


Solution

  • Something like:

    useEffect(() => {
        if(window.myButton) window.myButton.close();
        window.myButton = window.paypal
          .Buttons({
            createOrder: (data, actions) => {
              return actions.order.create({
                purchase_units: [
                  {
                    description: "test",
                    amount: {
                      currency_code: "USD",
                      value: props.price
                    }
                  }
                ]
              });
            },
            onApprove: async (data, actions) => {
              const order = await actions.order.capture();
              console.log(order);
            },
            onError: err => {
              setError(err);
              console.error(err);
            }
          });
        window.myButton.render(paypalRef.current);
    

    However, you do not actually need to re-render the button on price change!

    You can do value: document.getElementById('...').value or similar (or whatever variable or function call you need)

    In your example, if props.price returns the (new/current) desired value when the button is clicked, then that value will be used.

    Basically, the createOrder function isn't called until you click a button.