HOW - React Router v6.x Feature 实践(react-router-dom)

07-08 1087阅读

目录

  • 基本特性
  • ranked routes matching
  • active links
    • NavLink
    • useMatch
    • relative links
        • 1. 相对路径的使用
        • 2. 嵌套路由的增强行为
        • 3. 优势和注意事项
        • 4. . 和 ..
        • 5. 总结
        • data loading
        • loading or changing data and redirect
        • pending navigation ui
        • skeleton ui with suspense
        • data mutations with ``
        • busy indicators with route actions
        • data fetchers

          基本特性

          1. client side routing
          2. nested routes
          3. dynamic segments

          比较好理解,这里不赘述。

          HOW - React Router v6.x Feature 实践(react-router-dom)
          (图片来源网络,侵删)

          ranked routes matching

          https://reactrouter.com/en/main/start/overview#ranked-route-matching

          When matching URLs to routes, React Router will rank the routes according to the number of segments, static segments, dynamic segments, splats, etc. and pick the most specific match.

          这句话描述了 React Router 在匹配 URL 和路由时的策略,即根据路由的具体性来优先选择最合适的匹配项。让我们逐步解析这句话的含义:

          1. URL 和路由的匹配:

            • 当用户访问某个 URL 时,React Router 需要确定哪个路由规则最适合处理该 URL。例如,对于 URL /users/123,React Router 需要决定是匹配 /users/:id 还是其他定义的路由。
            • 路由匹配的考量因素:优先级由高到低

              • 路由的段数(Segments):URL 和路由可以分成多个段(segments),例如 /users/123 有两个段,/users/:id 也有两个段。React Router 会比较 URL 和每个路由的段数,越多的段数一般意味着路由更具体。

              • 静态段(Static Segments):静态段是指在路由中直接指定的固定路径,例如 /users 是一个静态段。React Router 会考虑静态段的数量来确定路由的具体性。

              • 动态段(Dynamic Segments):动态段是指在路由中使用参数化路径,例如 /users/:id 中的 :id 是一个动态段。动态段的存在可能使得路由更灵活但也更具体。

              • 通配符(Splat):通配符(如 *)表示匹配多个路径段,通常用于处理不确定数量的路径部分。

              • 最具体的匹配:

                • React Router 会通过比较以上因素来确定哪个路由定义是最具体的匹配。具体的路由定义意味着它能够最准确地匹配当前的 URL,而不会与其他可能的路由定义冲突。
                • 示例:

          
          

          对于 http://example.com/teams/new. 会优先匹配第二个 Route。因为静态段数为 2,更具体。

          理解 React Router 的路由匹配策略,特别是根据路由的具体性来优先选择最合适的匹配项,有助于开发者更有效地设计和管理复杂的路由结构。通过正确的路由定义和优先级排序,可以确保应用程序在导航和页面渲染时行为符合预期,并能够灵活地应对各种场景和URL路径。

          active links

          NavLink

          https://reactrouter.com/en/main/components/nav-link

           {
              return {
                color: isActive ? "red" : "inherit",
              };
            }}
            className={({ isActive, isPending }) => {
              return isActive ? "active" : isPending ? "pending" : "";
            }}
          />
          

          useMatch

          https://reactrouter.com/en/main/hooks/use-match

          function SomeComp() {
            const match = useMatch("/messages");
            return 
        • ; }

          relative links

          理解 React Router 中 和 组件相对路径的使用需要考虑它们与 HTML 中 标签的行为差异,尤其是在嵌套路由场景下的增强行为。

          1. 相对路径的使用

          • HTML 标签:在 HTML 中,使用 标签时,相对路径通常相对于当前页面的完整 URL。这意味着,相对路径会根据当前页面的路径来构建最终的目标 URL。

            About
            
            • 如果当前 URL 是 http://example.com/home,那么点击上述链接将导航到 http://example.com/https://blog.csdn.net/weixin_58540586/article/details/about。
            • React Router 中的 和 :在 React Router 中, 和 组件可以接受相对路径,但它们的行为略有不同。

              import { Link, NavLink } from 'react-router-dom';
              About
              About
              
              • 这里的 to="https://blog.csdn.net/weixin_58540586/article/details/about" 是相对路径,相对于当前路由的路径来构建目标 URL。例如,如果当前路由是 /home,那么这两个链接将会导航到 /home/https://blog.csdn.net/weixin_58540586/article/details/about。

                2. 嵌套路由的增强行为

                • 嵌套路由:当应用程序中存在嵌套路由时,React Router 的 和 组件表现出更智能的行为,确保相对路径的正确解析。

                    About
                    About
                  
                  
                  • 在上述例子中,假设当前路由是 /home,那么 和 组件会基于当前路由的路径 /home 构建相对路径,导航到 /home/https://blog.csdn.net/weixin_58540586/article/details/about。

                    3. 优势和注意事项

                    • 灵活性和便利性:相对路径的使用使得在应用中链接管理更加灵活和简单,尤其是在处理嵌套路由时。

                    • 注意路径解析:确保理解相对路径在不同嵌套层级下的解析规则。React Router 的行为通常是基于当前活动的路由来解析相对路径,而不是简单地相对于根路径。

                      4. . 和 …

                        About
                        About
                      
                      
                      • 在上述例子中,假设当前路由是 /home,那么 和 组件会基于当前路由的路径 /home 构建相对路径,导航到 /home。
                          
                          	
                          
                        
                        

                        Project 中会渲染:

                          
                          
                          
                          
                        
                        • 在上述例子中,假设当前路由是 /home/project/123,那么 会基于当前路由的路径构建相对路径,分别导航到 /home/project/123/abc、/home/project/abc、/home、/home/project。

                          注意后面两个的差异:

                          By default, the … in relative links traverse the route hierarchy, not the URL segments. Adding relative=“path” in the next example allows you to traverse the path segments instead.

                          5. 总结

                          理解 React Router 中 和 组件相对路径的行为,特别是在嵌套路由情况下的增强行为,有助于开发者更有效地管理和导航应用程序中的链接。相对路径的使用使得在不同层级和场景下的导航操作更加灵活和便捷,但需要注意理解和控制路径的解析和构建规则。

                          data loading

                          https://reactrouter.com/en/main/start/overview#data-loading

                          Combined with nested routes, all of the data for multiple layouts at a specific URL can be loaded in parallel.

                           {
                              // loaders can be async functions
                              const res = await fetch("/api/user.json", {
                                signal: request.signal,
                              });
                              const user = await res.json();
                              return user;
                            }}
                            element={}
                          >
                             {
                                return fetch(`/api/teams/${params.teamId}`);
                              }}
                              element={}
                            >
                               {
                                  // of course you can use any data store
                                  return fakeSdk.getTeam(params.gameId);
                                }}
                                element={}
                              />
                            
                          
                          

                          Data is made available to your components through useLoaderData.

                          function Root() {
                            const user = useLoaderData();
                            // data from 
                          }
                          function Team() {
                            const team = useLoaderData();
                            // data from 
                          }
                          function Game() {
                            const game = useLoaderData();
                            // data from 
                          }
                          

                          When the user visits or clicks links to https://example.com/real-salt-lake/45face3, all three route loaders will be called and loaded in parallel, before the UI for that URL renders.

                          loading or changing data and redirect

                          https://reactrouter.com/en/main/route/loader#throwing-in-loaders

                           {
                              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 };
                            }}
                          />
                          

                          pending navigation ui

                          https://reactrouter.com/en/main/start/overview#pending-navigation-ui

                          When users navigate around the app, the data for the next page is loaded before the page is rendered. It’s important to provide user feedback during this time so the app doesn’t feel like it’s unresponsive.

                          function Root() {
                            const navigation = useNavigation();
                            return (
                              
                                {navigation.state === "loading" && }
                                
                                
                                
                              
                            );
                          }
                          

                          skeleton ui with suspense

                          https://reactrouter.com/en/main/start/overview#skeleton-ui-with-suspense

                          Instead of waiting for the data for the next page, you can defer data so the UI flips over to the next screen with placeholder UI immediately while the data loads.

                          defer enables suspense for the un-awaited promises

                           {
                              // 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 {/* ... */};
                          }
                          

                          涉及如下 API 结合使用:

                          1. defer
                          2. Await
                          3. useAsyncValue

                          data mutations with

                          https://reactrouter.com/en/main/start/overview#data-mutations

                          HTML forms are navigation events, just like links. React Router supports HTML form workflows with client side routing.

                          When a form is submitted, the normal browser navigation event is prevented and a Request, with a body containing the FormData of the submission, is created. This request is sent to the that matches the form’s .

                          Form elements’s name prop are submitted to the action:

                            
                              Project title
                              
                          Target Finish Date
                           {
                              const formData = await request.formData();
                              const newProject = await createProject({
                                title: formData.get("title"),
                                due: formData.get("due"),
                              });
                              return redirect(`/projects/${newProject.id}`);
                            }}
                          />
                          

                          在 HTML 中, 元素的 action 属性定义了当用户提交表单时将数据发送到的服务器端的 URL。

                          具体来说:

                          • action 属性的作用:

                            • 当用户提交表单时,浏览器会将表单中的数据发送到指定的 URL。
                            • 这个 URL 可以是相对路径或绝对路径。
                            • 如果 action 属性未指定,表单会被提交到当前页面的 URL(即自身)。
                            • 使用示例:

                                  
                                  
                                  提交
                              
                              
                              • 在这个例子中,action 属性的值是 "/project/new"。当用户点击提交按钮时,表单数据将被发送到当前服务器的 /project/new 路径。
                              • 重要说明:

                                • 如果 action 属性指向一个相对路径,表单数据会被提交到当前页面的基础 URL 加上 action 的值。
                                • 如果 action 属性是绝对路径(例如 http://example.com/project/new),数据将被发送到指定的绝对路径。
                                • HTTP 方法 (method 属性):

                                  • 另一个与 action 相关的重要属性是 method,它指定了使用何种 HTTP 方法将表单数据发送到服务器。
                                  • 常见的方法是 GET 和 POST。GET 方法将数据附加到 URL 上(可见),而 POST 方法将数据包含在请求体中(不可见)。

                                    总结来说,action 属性定义了表单数据提交的目标 URL。这对于将用户输入数据发送到后端处理或其他指定的处理程序非常重要。

                                    busy indicators with route actions

                                    https://reactrouter.com/en/main/start/overview#busy-indicators

                                    When forms are being submitted to route actions, you have access to the navigation state to display busy indicators, disable fieldsets, etc.

                                    function NewProjectForm() {
                                      const navigation = useNavigation();
                                      const busy = navigation.state === "submitting";
                                      return (
                                        
                                          
                                            
                                              Project title
                                              
                                    Target Finish Date
                                    {busy ? "Creating..." : "Create"} ); }

                                    data fetchers

                                    HTML Forms are the model for mutations but they have one major limitation: you can have only one at a time because a form submission is a navigation.

                                    Most web apps need to allow for multiple mutations to be happening at the same time, like a list of records where each can be independently deleted, marked complete, liked, etc.

                                    Fetchers allow you to interact with the route actions and loaders without causing a navigation in the browser, but still getting all the conventional benefits like error handling, revalidation, interruption handling, and race condition handling.

                                    Imagine a list of tasks:

                                    function Tasks() {
                                      const tasks = useLoaderData();
                                      return tasks.map((task) => (
                                        
                                          

                                    {task.name}

                                    )); }

                                    Each task can be marked complete independently of the rest, with its own pending state and without causing a navigation with a fetcher:

                                    function ToggleCompleteButton({ task }) {
                                      const fetcher = useFetcher();
                                      return (
                                        
                                          
                                            
                                            
                                            
                                              {task.status === "complete"
                                                ? "Mark Incomplete"
                                                : "Mark Complete"}
                                            
                                          
                                        
                                      );
                                    }
                                    
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]