如何在 react-router-dom 6 中将 props 传递给 Layout Routes

How to pass props to Layout Routes in react-router-dom 6

我在官方 React Router 文档中找不到如何将 props 从嵌套路由传递到 Layout 路由(页面)。我使用 useRoutes 挂钩而不是 <Routes>

正如您从提供的代码中看到的那样,我想从 children 路线(登录、InvestorRegister、ServiceProviderRegister、ForgotPassword、ResetPassword)向布局路线包装页面 (LeftImageLayout) ).

怎么做?任何建议或代码改进将不胜感激。谢谢

我知道我可以使用 ContextApi 将道具从 parent 传递到 child,但我不能这样做。

布局

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;

路线

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" />
          ),
        },
      ],
    },
    ...
  ]);
}

登录

const Login = () => {
  return ( // Place for React hook form );
};

export default Login;

您可以使用 useState 钩子。在 Routes 中,您需要添加以下代码:

const [image, setImage] = useState('')
const [text, setText] = useState('')

我不确定您是否需要在子组件中同时设置和显示图像和文本。为了让您的生活更轻松一些,您可能希望将该状态放入您将作为道具传递的对象中:

const params = {
  image,
  setImage,
  text,
  setText
}

这将是您的 children 数组中的示例条目:

{
  path: "/login",
  element: <Login params={params} />,
}

Login 组件中,您将添加以下内容:

const Login = ({ params }) => {
  const { setImage, setText } = params
  
  useEffect(() => {
    setText('Text for login page')
    setImage('4')
  }, [])
  
  //...
}

LeftImageLayout 也会将 params 作为道具,不同之处在于你在解构 [=18= 时会访问 textimage 值].

我将使用 window.location.pathname 有条件地呈现内容(图像 ID 和文本),如下所示:

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>
  );
};

我们可以使用 hook useLocation()

而不是 window.location.pathname