skip to Main Content

I have a project on React, and for layout, I am using an old version. I want to use the new version of react-router-dom but I have some problems. These are my codes.

App.js

<Route element={<AuthLayout />}>
  <Route element={<LoginPage />} path="/login" />
  <Route element={<RegisterPage />} path="/register" />
  <Route element={<ForgotPassword />} path="/forgotPassword" />
  <Route element={<Verify />} path="/forgotpassword/verify" />
</Route>

But AuthLayout is old coding. And it works.

const AuthLayout = ({ page, children, img }) => {
  return (
    <main className={`auth-layout ${page}`}>
      {children}
      <div className="images">
        <img src={img} alt={page} />
        <img src={Logo} alt="Logo" className="logo" />
      </div>
    </main>
  );
};

I want to use Outlet and useOutletContext, but I don’t know how I can send page and img props? I don’t get this topic very correctly.

One of my child props – ForgotPassword

import ForgotImg from "assets/img/forgot-password.svg";

<AuthLayout page="forgot-password" img={ForgotImg}>
  <form onClick={sendPassword}>

  </form>
</AuthLayout>

2

Answers


  1. Clear the AuthLayout wrapper from your child component:

    import ForgotImg from "assets/img/forgot-password.svg";
      <form onClick={sendPassword}>
    
      </form>
    

    Add Outlet instead of {children}

    import {Outlet} from "react-router-dom"  
    
    const AuthLayout = ({ page, children, img }) => {
    return (
    <main className={`auth-layout ${page}`}>
      <Outlet />
      <div className="images">
        <img src={img} alt={page} />
        <img src={Logo} alt="Logo" className="logo" />
      </div>
    </main>`  
    );
    };`
    

    I guess you do not need to use useOutletContext hook if you are not passing any props from AuthLayout to its children.

    Login or Signup to reply.
  2. If I understand the question correctly you are asking for how routed children/nested routes can pass up a page and img value to the parent layout route that it can then render.

    You could do this with a layout route with some state and callbacks that are passed down via a Context provider, and a wrapper component that accesses the context and passes the values up.

    Example:

    const AuthLayout = () => {
      const [{ img, page }, setState] = React.useState({});
    
      const setPageData = React.useCallback(
        ({ img, page }) => setState({ img, page }),
        []
      );
      
      return (
        <main className={`auth-layout ${page}`}>
          <Outlet context={{ setPageData }} />
          <div className="images">
            <img src={img} alt={page} />
            <img src={Logo} alt="Logo" className="logo" />
          </div>
        </main>
      );
    };
    
    const withPageData = (Component, { img, page }) => (props) => {
      const { setPageData } = useOutletContext();
    
      useEffect(() => {
        setPageData({ img, page });
      }, [img, page, setPageData]);
    
      return <Component {...props} />;
    }
    
    import ForgotImg from "assets/img/forgot-password.svg";
    
    ...
    
    const ForgotPassword = (props) => {
      ...
    
      return (
        ...
        <form onClick={sendPassword}>
    
        </form>
        ...
      );
    };
    
    const pageData = { page: "forgot-password", img: ForgotImg };
    
    export default withPageData(ForgotPassword, pageData);
    
    <Route element={<AuthLayout />}>
      <Route element={<LoginPage />} path="/login" />
      <Route element={<RegisterPage />} path="/register" />
      <Route element={<ForgotPassword />} path="/forgotPassword" />
      <Route element={<Verify />} path="/forgotpassword/verify" />
    </Route>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search