# vite-react-route **Repository Path**: panws/vite-react-route ## Basic Information - **Project Name**: vite-react-route - **Description**: react-router v6 官方教程案例 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-04-19 - **Last Updated**: 2024-04-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # React + Vite + react-router-dom 官方案例实战 ### 保存路径历史 ```jsx export async function loader({ request }) { const url = new URL(request.url); const q = url.searchParams.get("q"); const contacts = await getContacts(q); return { contacts, q }; } ``` ## 客户端路由 ### 1. 加载数据 loader 加载数据并将数据返回给组件 ```jsx { const user = await fake.getUser(); if (!user) { // if you know you can't render the route, you can // throw a redirect to stop executing code here, // sending the user to a new route throw redirect("/login"); } // otherwise continue const stats = await fake.getDashboardStats(); return { user, stats }; }} /> ``` 加载数据,发生重定向 ```jsx { const data = await request.formData(); const newProject = await createProject(data); // it's common to redirect after actions complete, // sending the user to the new record return redirect(`/projects/${newProject.id}`); }} /> ``` - 待定导航用户界面,显示加载 loading - 当用户浏览应用程序时,下一页的数据会在页面呈现之前加载。在这段时间内提供用户反馈非常重要,这样才不会让人感觉应用程序反应迟钝。 ```jsx function Root() { const navigation = useNavigation(); return (
{navigation.state === "loading" && }
); } ``` 带有``的骨架屏用户界面 ```jsx } loader={async ({ params }) => { // these are promises, but *not* awaited const comments = fake.getIssueComments(params.issueId); const history = fake.getIssueHistory(params.issueId); // the issue, however, *is* awaited const issue = await fake.getIssue(params.issueId); // defer enables suspense for the un-awaited promises return defer({ issue, comments, history }); }} />; function Issue() { const { issue, history, comments } = useLoaderData(); return (
{/* Suspense provides the placeholder fallback */} }> {/* Await manages the deferred data (promise) */} {/* this calls back when the data is resolved */} {(resolvedHistory) => } }> {/* ... or you can use hooks to access the data */}
); } function IssueComments() { const comments = useAsyncValue(); return
{/* ... */}
; } ``` ### 2.提交数据(数据突变) action ```jsx
{ const formData = await request.formData(); const newProject = await createProject({ title: formData.get("title"), due: formData.get("due"), }); return redirect(`/projects/${newProject.id}`); }} /> ``` #### 数据重新验证 几十年前的网络惯例表明,当表单发布到服务器时,数据就会发生变化,并渲染新的页面。React Router 基于 HTML 的数据突变 API 遵循了这一惯例。 调用路由操作后,页面上所有数据的加载器将再次被调用,以确保用户界面自动保持最新数据。无需过期缓存键,无需重新加载上下文提供程序。 #### 繁忙的指示器,显示提交中 当表单提交到路由操作时,您可以访问导航状态,以显示繁忙指示器、禁用字段集等。 ```jsx function NewProjectForm() { const navigation = useNavigation(); const busy = navigation.state === "submitting"; return (
); } ``` ### 3. 优化用户界面 即使异步工作仍处于待处理状态,了解发送到 action 的 formData 通常也足以跳过繁忙指示器,立即以下一状态渲染用户界面。这就是所谓的 "优化用户界面"。 ```jsx function LikeButton({ tweet }) { const fetcher = useFetcher(); // if there is `formData` then it is posting to the action const liked = fetcher.formData ? // check the formData to be optimistic fetcher.formData.get("liked") === "yes" : // if its not posting to the action, use the record's value tweet.liked; return ( ); } ``` ### 4. 竞争条件处理, 无需防抖和节流了 - 如果使用 React Router 的数据约定,就可以完全自动地避免这个问题。 - React Router 不仅能处理类似导航的竞争条件,还能处理许多其他情况,如加载自动完成的结果或使用 fetcher 执行多个并发突变(及其自动并发重验证)。 ```jsx ?q=ry |-----------X ^ cancel wrong state when correct state completes earlier ?q=ryan |--------| ^ commit correct state ``` ### 5. 错误处理 React Router 会自动处理应用程序中的绝大多数错误。它将捕获在以下情况下抛出的任何错误: - 渲染 - 加载数据 - 更新数据 在实践中,除了在事件处理程序( `