Pages and Layouts#

We adopt page and layout capabilities based on file directory structure, which means you can use file directories to manage your pages and layouts.

In this chapter, we will provide a complete guide on how to create pages and layouts.

Creating Pages#

Pages are interface components displayed on specific routes. We define files ending with .page.tsx as page files, and the route address is mapped according to the directory hierarchy structure where the page file is located.

Let's create our first page by creating an order directory under the src/pages directory, and then creating an Order.page.tsx file to export a component.

Basic routing demonstration

// src/pages/order/Order.page.tsx export default function Order() { return <div>Order Page</div> }

It's worth noting that when the directory structure is finally mapped to route addresses, if the last directory name is index, that part of the route address mapping will be automatically omitted.

Check out the following examples to help you understand this:

Page File DirectoryRoute Address
src/pages/index/Index.page.tsx/
src/pages/order/index/Order.page.tsx`/order
src/pages/ware/index/detail/Detail.page.tsx`/ware/index/detail

Dynamic Routes#

We can specify dynamic routes by adding brackets to directory names, such as [id].

Let's add a page file in the src/pages/order/[id]/detail directory and export a component.

Dynamic route demonstration

[id] will be mapped as a dynamic parameter, and you can get the current parameter value using useParams().

// src/pages/order/[id]/detail/Detail.page.tsx import { useParams } from "wiscore/router" export default function Detail() { const { id } = useParams(); return <div>Order Detail id: {id}</div>; }

Creating Layouts#

Layouts are shared interface layouts between multiple pages, commonly used to implement common parts of a website, such as menu bars, navigation bars, user avatars, etc. The layouts here are different from layout systems in other frameworks. To achieve the feature of quick adaptation to multiple scenarios, we reflect layouts in route addresses. Changing the route address can quickly switch layouts, which becomes very convenient when applications need to be displayed with different layouts in different scenarios.

We define files ending with .layout.tsx as layout files, and the direct parent directory of the layout file will be mapped as the layout route.

If your project doesn't already have a src/layouts directory, please create it first. This directory will serve as a unified directory for storing all layouts. Next, we'll create the first layout by creating an index directory in that directory, and creating an Index.layout.tsx file to export a component.

Layout demonstration

// src/layouts/index/Index.layout.tsx export default function IndexLayout({ children }) { return ( <main> <header>App Header</header> {children} </main> ); }

When you want to access the previously created order page with index as the layout, simply access the address /index/order.

With this capability, you can write multiple layouts for your project and access different layouts in different pages and scenarios.

Check out the following examples to fully understand how layouts are mapped:

Layout File DirectoryLayout Route
src/layouts/index/Index.layout.tsx/index
src/layouts/container/column/Column.layout.tsx/column

From the examples above 👆, we can see that the layout route only recognizes the first-level parent directory. Folder nesting only provides a way to manage and categorize layouts.

Route Composition#

In addition to reflecting the pages, layouts, and parameters described above, route addresses also reflect a type of route segment, which is the application. We won't introduce the concept of applications in this chapter, but since route-related APIs will involve applications, we briefly mention it. Once you've completed the application chapter, it will be easy to understand.

Route composition

Route Switching#

We provide several commonly used route operation APIs that enable quick route switching.

import { useNavigate } from "wiscore/router"; function () { const navigate = useNavigate(); return ( <button onClick={() => navigate("/order")}> Navigate to order page </button> ); }

And they all follow the same set of switching rules:

  • When the address about to be switched doesn't contain application and layout paths, it will automatically take the application and layout paths from the current address
  • When the address about to be switched contains an application path, it will automatically take the layout path from the current address
  • When the address about to be switched contains a layout path, the current layout and application become invalid.