I couldn't find in official React Router Documentation how to pass props from nested routes to Layout route (page). Instead of <Routes>
I am using useRoutes
hook.
As you can see from provided code, I want to provide props (image id and title) from children routes (Login, InvestorRegister, ServiceProviderRegister, ForgotPassword, ResetPassword) to layout route wrapper page (LeftImageLayout).
How to do that? Any suggestions or code improvment will be appreciated. Thank you
I know that I can use ContextApi
to pass props from parent to child, but I can't do that in my case.
Layout
import { Outlet } from "react-router-dom";
import { styled } from "@mui/material/styles";
import Typography from "@mui/material/Typography";
import Grid from "@mui/material/Grid";
const Wrapper = styled("div")({
backgroundSize: "cover",
backgroundRepeat: "no-repeat",
minHeight: "100vh",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
});
const LeftImageLayout = ({ image, text }) => {
return (
<Grid container spacing={0} justifyContent="center" alignItems="center">
<Grid item xs={12} md={8}>
<Wrapper
sx={{
background: `url("https://picsum.photos/1280/957?random=${image}")`,
}}
>
<Typography
variant="h1"
sx={{ alignSelf: "flex-start", paddingLeft: 2, paddingTop: 2 }}
>
BuildUp
</Typography>
<Typography variant="h2" sx={{ alignSelf: "center" }}>
{text}
</Typography>
<Typography variant="span" />
</Wrapper>
</Grid>
<Grid item xs={12} md={4}>
<Outlet />
</Grid>
</Grid>
);
};
export default LeftImageLayout;
Routes
export default function Router() {
return useRoutes([
...
{
element: <LeftImageLayout />,
children: [
{
path: "/login",
element: <Login text="Text for login page" image="4" />,
},
{
path: "/investor-registration",
element: <InvestorRegister text="Text for investor page" image="5" />,
},
{
path: "/service-provider-registration",
element: (
<ServiceProviderRegister
text="Text for service provider page"
image="6"
/>
),
},
{
path: "/forgot-password",
element: (
<ForgotPassword text="Text for forgot password page" image="6" />
),
},
{
path: "/reset-password",
element: (
<ResetPassword text="Text for reset password page" image="7" />
),
},
],
},
...
]);
}
Login
const Login = () => {
return ( // Place for React hook form );
};
export default Login;
CodePudding user response:
You could use useState
hook. In Routes, you'd need to add this code:
const [image, setImage] = useState('')
const [text, setText] = useState('')
I'm not sure if you need to both set and display image and text in your children components. To make your life a little bit easier, you'd probably want to put that state into an object that you'd pass as a prop:
const params = {
image,
setImage,
text,
setText
}
This would be an example entry in your children
array:
{
path: "/login",
element: <Login params={params} />,
}
In Login
component, you'd add the following:
const Login = ({ params }) => {
const { setImage, setText } = params
useEffect(() => {
setText('Text for login page')
setImage('4')
}, [])
//...
}
LeftImageLayout
would take params
as a prop, as well, the diference being that you'd access text
and image
values when deconstructing params
.
CodePudding user response:
I will use window.location.pathname
to conditionally render content (image id and text), like this:
const LeftImageLayout = () => {
const pathName = window.location.pathname.substring(1);
let image = "";
let text = "";
switch (pathName) {
case "login":
text = "Hundreds of on-demand workers are open to work!";
image = "1";
break;
case "investor-registration":
text =
"Access the selection of hundreds construction related on demand workers, ready to work with you.";
image = "2";
break;
case "service-provider-registration":
text =
"Offer your services to a various investors looking for talented construction related people like you.";
image = "3";
break;
case "forgot-password":
text =
"We help talents in construction related services connect with local investors.";
image = "4";
break;
case "reset-password":
text =
"Talents and experienced investors combined to bring extraordinary results.";
image = "5";
break;
default:
break;
}
return (
<Grid container spacing={0} justifyContent="center" alignItems="center">
<Grid item xs={12} md={8}>
<Wrapper
sx={{
background: `url("https://picsum.photos/1280/957?random=${image}")`,
}}
>
<Typography
variant="h1"
sx={{ alignSelf: "flex-start", paddingLeft: 2, paddingTop: 2 }}
>
BuildUp
</Typography>
<Typography variant="h2" sx={{ alignSelf: "center" }}>
{text}
</Typography>
<Typography variant="span" />
</Wrapper>
</Grid>
<Grid item xs={12} md={4}>
<Outlet context={{ image, text }} />
</Grid>
</Grid>
);
};
Instead of window.location.pathname
we can use hook useLocation()