I was trying to integrate the strip API key but I am not able to come up with the solution in the new react-router-dom version
here is the full error
The above error occurred in the component:
at Routes (http://localhost:3000/static/js/bundle.js:81119:5)
at Router (http://localhost:3000/static/js/bundle.js:81052:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:79861:5)
at App (http://localhost:3000/main.79cc3231add2da1b35a8.hot-update.js:89:63)
at Provider (http://localhost:3000/static/js/bundle.js:74963:5)
Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
here is my Appjs Protected route code:
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";
useEffect(() => {
store.dispatch(loadUser());
getStripeApiKey();
}, []);
useEffect(() => {
const stripePromise= loadStripe(stripeApiKey);
}, [stripeApiKey]);
<Route element={<ProtectedRoute />}>
<Route path="/account" element={<Profile />} />
<Route path="/me/update" element={<ProfileEdit />} />
<Route path="/password/update" element={<UpdatePassword />} />
<Route path="/login/shipping" element={<Shipping />} />
<Route path="/order/confirm" element={<ConfirmOrder />} />
{stripeApiKey && (
<Elements stripe={stripePromise}>
<Route path="/order/payment" element={<Payment />} />
</Elements>
)}
</Route>
My protected route code
const ProtectedRoute = () => {
const { loading, isAuthenticated, user } = useSelector((state) => state.user);
const location = useLocation();
if (isAuthenticated == false) {
return <Navigate to="/account" state={{ from: location }} />;
}
return <Outlet />;
};
export default ProtectedRoute;
CodePudding user response:
You are getting that error because of this line of code
{stripeApiKey && (
<Elements stripe={stripePromise}>
<Route path="/order/payment" element={<Payment />} />
</Elements>
)}
Only Route or React.Fragment are allowed to be children of the Routes component. But in your case if stripeApiKey turns out to be true , you are rendering Elements component which contradicts the new react router v6 rules
Like you asked in comments you want to wrap your payments method
<Route path="/order/payment" element={<Elements stripe={stripePromise}><Payment /></Elements} />
CodePudding user response:
Issue
This issue is that you are rendering something other than a Route
or React.Fragment
inside the Routes
component.
{stripeApiKey && (
<Elements stripe={stripePromise}>
<Route path="/order/payment" element={<Payment />} />
</Elements>
)}
The Elements
component is neither and fails the invariant check.
Solution
Refactor this into a layout route component similar to the ProtectedRoute
component.
Example:
import { Outlet, Navigate } from 'react-router-dom';
const StripeLayout = ({ stripeApiKey }) => {
return stripeApiKey
? <Outlet />
: <Navigate to="/" replace />
};
...
<Route element={<ProtectedRoute />}>
<Route path="/account" element={<Profile />} />
<Route path="/me/update" element={<ProfileEdit />} />
<Route path="/password/update" element={<UpdatePassword />} />
<Route path="/login/shipping" element={<Shipping />} />
<Route path="/order/confirm" element={<ConfirmOrder />} />
<Route element={<StripeLayout {...{ stripeApiKey }} />}>
<Route
path="/order/payment"
element={(
<Elements stripe={stripePromise}>
<Payment />
</Elements>
)}
/>
</Route>
</Route>