0
// file _app.js
import \"../styles/globals.css\";
import { SessionProvider, useSession } from \"next-auth/react\";
import { StoreProvider } from \"../utils/Store\";
import { useRouter } from \"next/router\";
import { PayPalScriptProvider } from \"@paypal/react-paypal-js\";
  function App({ Component, pageProps: { session, ...pageProps } }) {
  return (
    <SessionProvider session={session}>
      <StoreProvider>
        <PayPalScriptProvider deferLoading={true}>
          {Component.auth ? (
            <Auth>
              <Component {...pageProps} />
            </Auth>
          ) : (
            <Component {...pageProps} />
          )}
        </PayPalScriptProvider>
      </StoreProvider>
    </SessionProvider>
  );
}
  function Auth({ children }) {
  const router = useRouter();
  const { status } = useSession({
    required: true,
    onUnauthenticated() {
      router.push(\"/unauthorized?message=login required\");
    }
  });
  if (status === \"loading\") {
    return <div>Loading...</div>;
  }
    return children;
}
  export default App;

// file orderscreen
import { PayPalButtons, usePayPalScriptReducer } from \"@paypal/react-paypal-js\";
import axios from \"axios\";
import Image from \"next/image\";
import Link from \"next/link\";
import { useRouter } from \"next/router\";
import { useEffect, useReducer } from \"react\";
import { toast } from \"react-toastify\";
import Layout from \"../../components/Layout\";
import { getError } from \"../../utils/error\";
 function reducer(state, action) {
  switch (action.type) {
    case \"FETCH_REQUEST\":
      return { ...state, loading: true, error: \"\" };
    case \"FETCH_SUCCESS\":
      return { ...state, loading: false, order: action.payload, error: \"\" };
    case \"FETCH_FAIL\":
      return { ...state, loading: false, error: action.payload };
    case \"PAY_REQUEST\":
      return { ...state, loadingPay: true };
    case \"PAY_SUCCESS\":
      return { ...state, loadingPay: false, successPay: true };
    case \"PAY_FAIL\":
      return { ...state, loadingPay: false, errorPay: action.payload };
    case \"PAY_RESET\":
      return { ...state, loadingPay: false, successPay: false, errorPay: \"\" };
     default:
      state;
  }
}
function OrderScreen() {
  // order/:id
  const [{ isPending }, paypalDispatch] = usePayPalScriptReducer();
   const { query } = useRouter();
  const orderId = query.id;
   const [{ loading, error, order, successPay, loadingPay }, dispatch] =
    useReducer(reducer, {
      loading: true,
      order: {},
      error: \"\"
    });
  useEffect(() => {
    const fetchOrder = async () => {
      try {
        dispatch({ type: \"FETCH_REQUEST\" });
        const { data } = await axios.get(`/api/orders/${orderId}`);
        dispatch({ type: \"FETCH_SUCCESS\", payload: data });
      } catch (err) {
        dispatch({ type: \"FETCH_FAIL\", payload: getError(err) });
      }
    };
    if (!order._id || successPay || (order._id && order._id !== orderId)) {
      fetchOrder();
      if (successPay) {
        dispatch({ type: \"PAY_RESET\" });
      }
    } else {
      const loadPaypalScript = async () => {
        const { data: clientId } = await axios.get(\"/api/keys/paypal\");
        paypalDispatch({
          type: \"resetOptions\",
          value: {
            \"client-id\": clientId,
            currency: \"USD\"
          }
        });
        paypalDispatch({ type: \"setLoadingStatus\", value: \"pending\" });
      };
      loadPaypalScript();
    }
  }, [order, orderId, paypalDispatch, successPay]);
  const {
    shippingAddress,
    paymentMethod,
    orderItems,
    itemsPrice,
    taxPrice,
    shippingPrice,
    totalPrice,
    isPaid,
    paidAt,
    isDelivered,
    deliveredAt
  } = order;
   function createOrder(data, actions) {
    return actions.order
      .create({
        purchase_units: [
          {
            amount: { value: totalPrice }
          }
        ]
      })
      .then((orderID) => {
        return orderID;
      });
  }
   function onApprove(data, actions) {
    return actions.order.capture().then(async function (details) {
      try {
        dispatch({ type: \"PAY_REQUEST\" });
        const { data } = await axios.put(
          `/api/orders/${order._id}/pay`,
          details
        );
        dispatch({ type: \"PAY_SUCCESS\", payload: data });
        toast.success(\"Order is paid successgully\");
      } catch (err) {
        dispatch({ type: \"PAY_FAIL\", payload: getError(err) });
        toast.error(getError(err));
      }
    });
  }
  function onError(err) {
    toast.error(getError(err));
  }
   return (
    <Layout title={`Order ${orderId}`}>
      <h1 className=\"mb-4 text-xl\">{`Order ${orderId}`}</h1>
      {loading ? (
        <div>Loading...</div>
      ) : error ? (
        <div className=\"alert-error\">{error}</div>
      ) : (
        <div className=\"grid md:grid-cols-4 md:gap-5\">
          <div className=\"overflow-x-auto md:col-span-3\">
            <div className=\"card  p-5\">
              <h2 className=\"mb-2 text-lg\">Shipping Address</h2>
              <div>
                {shippingAddress.fullName}, {shippingAddress.address},{\" \"}
                {shippingAddress.city}, {shippingAddress.postalCode},{\" \"}
                {shippingAddress.country}
              </div>
              {isDelivered ? (
                <div className=\"alert-success\">Delivered at {deliveredAt}</div>
              ) : (
                <div className=\"alert-error\">Not delivered</div>
              )}
            </div>
             <div className=\"card p-5\">
              <h2 className=\"mb-2 text-lg\">Payment Method</h2>
              <div>{paymentMethod}</div>
              {isPaid ? (
                <div className=\"alert-success\">Paid at {paidAt}</div>
              ) : (
                <div className=\"alert-error\">Not paid</div>
              )}
            </div>
             <div className=\"card overflow-x-auto p-5\">
              <h2 className=\"mb-2 text-lg\">Order Items</h2>
              <table className=\"min-w-full\">
                <thead className=\"border-b\">
                  <tr>
                    <th className=\"px-5 text-left\">Item</th>
                    <th className=\"    p-5 text-right\">Quantity</th>
                    <th className=\"  p-5 text-right\">Price</th>
                    <th className=\"p-5 text-right\">Subtotal</th>
                  </tr>
                </thead>
                <tbody>
                  {orderItems.map((item) => (
                    <tr key={item._id} className=\"border-b\">
                      <td>
                        <Link href={`/product/${item.slug}`}>
                          <a className=\"flex items-center\">
                            <Image
                              src={item.image}
                              alt={item.name}
                              width={50}
                              height={50}
                            ></Image>
                            &nbsp;
                            {item.name}
                          </a>
                        </Link>
                      </td>
                      <td className=\" p-5 text-right\">{item.quantity}</td>
                      <td className=\"p-5 text-right\">${item.price}</td>
                      <td className=\"p-5 text-right\">
                        ${item.quantity * item.price}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
          <div>
            <div className=\"card  p-5\">
              <h2 className=\"mb-2 text-lg\">Order Summary</h2>
              <ul>
                <li>
                  <div className=\"mb-2 flex justify-between\">
                    <div>Items</div>
                    <div>${itemsPrice}</div>
                  </div>
                </li>{\" \"}
                <li>
                  <div className=\"mb-2 flex justify-between\">
                    <div>Tax</div>
                    <div>${taxPrice}</div>
                  </div>
                </li>
                <li>
                  <div className=\"mb-2 flex justify-between\">
                    <div>Shipping</div>
                    <div>${shippingPrice}</div>
                  </div>
                </li>
                <li>
                  <div className=\"mb-2 flex justify-between\">
                    <div>Total</div>
                    <div>${totalPrice}</div>
                  </div>
                </li>
                {!isPaid && (
                  <li>
                    {isPending ? (
                      <div>Loading...</div>
                    ) : (
                      <div className=\"w-full\">
                        <PayPalButtons
                          createOrder={createOrder}
                          onApprove={onApprove}
                          onError={onError}
                        ></PayPalButtons>
                      </div>
                    )}
                    {loadingPay && <div>Loading...</div>}
                  </li>
                )}
              </ul>
            </div>
          </div>
        </div>
      )}
    </Layout>
  );
}
 OrderScreen.auth = true;
export default OrderScreen;

why there is Error: usePayPalScriptReducer must be used within a PayPalScriptProvider?
Can you help me?

DEV pq Asked question March 19, 2023