han*_*rig 5 javascript reactjs react-router react-router-dom
我正在尝试使用最新的 React Router 6.4 为 React Router Route 定义提供动态自定义道具。我找不到任何例子来展示我如何实现这一目标。这些是由RouterProvider声明的父组件提供的 props。
6.0 - 6.3官方文档的示例:
// Ah, nice and simple API. And it's just like the <Suspense> API!
// Nothing more to learn here.
<Route path=":userId" element={<Profile />} />
// But wait, how do I pass custom props to the <Profile>
// element? Oh ya, it's just an element. Easy.
<Route path=":userId" element={<Profile animate={true} />} />
Run Code Online (Sandbox Code Playgroud)
在 6.4 中,您的路由定义类似于:
// How do I provide animate state from App component to Policy component?
const router = createBrowserRouter([{ path: '/', element: <Profile animate={animate} /> }];
export function App() {
const [animate, setAnimate] = useState(true);
return <RouterProvider router={router} />
}
Run Code Online (Sandbox Code Playgroud)
Dre*_*ese 11
在您提供的示例中,您已经将一个animateprop 传递给了路由组件。RRDv6.4.0 没有更改Route组件 API。看来您的问题实际上是关于在访问路线时传递动态道具值。
将router声明移至组件中App,以便animate状态位于范围内。
例子:
function App() {
const [animate, setAnimate] = useState(true);
const router = createBrowserRouter([
{ path: "/", element: <Profile animate={animate} /> } // <-- pass prop value
]);
return (
<div className="App">
...
<RouterProvider router={router} />
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
为了避免router每次父组件重新渲染时都重新创建,您可以使用钩子来记忆它useMemo。
function App() {
const [animate, setAnimate] = useState(true);
const router = createBrowserRouter([
{ path: "/", element: <Profile animate={animate} /> } // <-- pass prop value
]);
return (
<div className="App">
...
<RouterProvider router={router} />
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
另一种选择是将状态移动到布局路由中,并通过布局路由的Outlet上下文提供程序向下传递状态。消费者使用useOutletContext钩子来访问提供的值。这意味着router可以将声明移出 React 组件并作为稳定的引用提供。
例子:
const Profile = () => {
const { animate } = useOutletContext();
...
return (
...
);
};
Run Code Online (Sandbox Code Playgroud)
const AppLayout = () => {
const [animate, setAnimate] = useState(true);
return (
<>
...
<Outlet context={{ animate, /* other values */ }} />
...
</>
);
};
const router = createBrowserRouter([
{
element: <AppLayout />,
children: [{ path: "/", element: <Profile /> }]
}
]);
export default function App() {
return (
<div className="App">
<RouterProvider router={router} />
</div>
);
}
Run Code Online (Sandbox Code Playgroud)