From 33eac195fd658f2a8192ee053b201d4fd3d03f82 Mon Sep 17 00:00:00 2001 From: Glenn Becker Date: Tue, 9 Aug 2022 22:50:42 -0600 Subject: [PATCH] docs: qwik-cty docs fix ups (#1002) --- .../routes/qwikcity/api/use-content/index.mdx | 2 +- .../qwikcity/api/use-document-head/index.mdx | 4 +- .../qwikcity/api/use-location/index.mdx | 11 ++- .../qwikcity/content/component/index.mdx | 7 +- .../src/routes/qwikcity/content/mdx/index.mdx | 7 +- .../routes/qwikcity/content/menu/index.mdx | 6 +- .../qwikcity/endpoint/overview/index.mdx | 22 ------ packages/docs/src/routes/qwikcity/menu.md | 13 ++-- .../{endpoint => routing}/data/index.mdx | 9 +-- .../qwikcity/routing/default-index/index.mdx | 23 ------ .../qwikcity/routing/endpoints/index.mdx | 25 +++++++ .../routing/error-responses/index.mdx | 70 ++++++++++++++++++ .../{endpoint => routing}/modify/index.mdx | 4 +- .../qwikcity/routing/overview/index.mdx | 68 ++++++++++++++---- .../qwikcity/routing/pathless/index.mdx | 6 +- .../non-200 => routing/redirects}/index.mdx | 71 +------------------ 16 files changed, 193 insertions(+), 155 deletions(-) delete mode 100644 packages/docs/src/routes/qwikcity/endpoint/overview/index.mdx rename packages/docs/src/routes/qwikcity/{endpoint => routing}/data/index.mdx (86%) delete mode 100644 packages/docs/src/routes/qwikcity/routing/default-index/index.mdx create mode 100644 packages/docs/src/routes/qwikcity/routing/endpoints/index.mdx create mode 100644 packages/docs/src/routes/qwikcity/routing/error-responses/index.mdx rename packages/docs/src/routes/qwikcity/{endpoint => routing}/modify/index.mdx (71%) rename packages/docs/src/routes/qwikcity/{endpoint/non-200 => routing/redirects}/index.mdx (51%) diff --git a/packages/docs/src/routes/qwikcity/api/use-content/index.mdx b/packages/docs/src/routes/qwikcity/api/use-content/index.mdx index e452729597b..1ed7a6aab1d 100644 --- a/packages/docs/src/routes/qwikcity/api/use-content/index.mdx +++ b/packages/docs/src/routes/qwikcity/api/use-content/index.mdx @@ -4,7 +4,7 @@ title: Qwik City - useContent() # Qwik City - `useContent()` -Use `useContent()` function retrieves the nearest content information for the current route. The returned object includes: +The `useContent()` function retrieves the nearest content information for the current route. The returned object includes: ```ts headings: ContentHeading[] | undefined; diff --git a/packages/docs/src/routes/qwikcity/api/use-document-head/index.mdx b/packages/docs/src/routes/qwikcity/api/use-document-head/index.mdx index 87083b1569e..14b695cf98c 100644 --- a/packages/docs/src/routes/qwikcity/api/use-document-head/index.mdx +++ b/packages/docs/src/routes/qwikcity/api/use-document-head/index.mdx @@ -4,9 +4,9 @@ title: Qwik City - useDocumentHead() # Qwik City - `useDocumentHead()` -Use `useDocumentHead()` to retrieve the document head metadata. +Use the `useDocumentHead()` function to retrieve the document head metadata. -`useDocumentHead()` retrieves `DocumentHead` object that will allow you to: +`useDocumentHead()` retrieves a `DocumentHead` object that will allow you to: - update the `title` in ``. - update the `meta` tags in ``. diff --git a/packages/docs/src/routes/qwikcity/api/use-location/index.mdx b/packages/docs/src/routes/qwikcity/api/use-location/index.mdx index ee90c3a38e7..587f7a02fbb 100644 --- a/packages/docs/src/routes/qwikcity/api/use-location/index.mdx +++ b/packages/docs/src/routes/qwikcity/api/use-location/index.mdx @@ -4,7 +4,16 @@ title: Qwik City - useLocation() # Qwik City - `useLocation()` -Use `useLocation()` to retrieve the current location (URL). +Use the `useLocation()` function to retrieve a `RouteLocation` object for the current location. + +```tsx +export interface RouteLocation { + readonly params: RouteParams; // Record + readonly href: string; + readonly pathname: string; + readonly query: Record; +} +``` The return value of `useLocation()` is similar to `document.location`, but it is safe to use on the server where there is no global `location` object. diff --git a/packages/docs/src/routes/qwikcity/content/component/index.mdx b/packages/docs/src/routes/qwikcity/content/component/index.mdx index 6194f7a88c2..5e17b8ae268 100644 --- a/packages/docs/src/routes/qwikcity/content/component/index.mdx +++ b/packages/docs/src/routes/qwikcity/content/component/index.mdx @@ -28,7 +28,8 @@ export default component$(() => { ## Importing other components -You can build complex views by composing multiple components within each other. To do that import other components like so: `import Heading from './path/to/component/heading';` to use it in the current component. +You can build complex views by composing multiple components within each other. To do that import other components into your index.tsx file. + ``` - src/ - components/ @@ -37,10 +38,10 @@ You can build complex views by composing multiple components within each other. - some/ - path/ - index.tsx # https://example.com/some/path - - _sub_component.tsx + - sub_component.tsx ``` -Inside `index.tsx` you can create a component that is exported as `default` export. Content is created by writing a template with [JSX](https://reactjs.org/docs/introducing-jsx.html)-Syntax. Every component-Function returns the template that should be rendered on the screen. If you want to learn more about the component anatomy, please see [components documentation](/docs/components/overview). +Inside `index.tsx` you can create a component that is exported as `default` export. Content is created by writing a template with [JSX](https://reactjs.org/docs/introducing-jsx.html)-Syntax. Every component-function returns the template that should be rendered on the screen. If you want to learn more about the component anatomy, please see [components documentation](/docs/components/overview). The following component will be rendered at `https://example.com/some/path` according to the directory-structure, we have set up above. ```typescript diff --git a/packages/docs/src/routes/qwikcity/content/mdx/index.mdx b/packages/docs/src/routes/qwikcity/content/mdx/index.mdx index 0c44c3da20b..9d2cb72f5e2 100644 --- a/packages/docs/src/routes/qwikcity/content/mdx/index.mdx +++ b/packages/docs/src/routes/qwikcity/content/mdx/index.mdx @@ -7,6 +7,7 @@ title: Qwik City - MDX An alternative way to author content is using `.mdx` files ([Markdown JSX](https://mdxjs.com/)). These files are authored as Markdown, but they are compiled down to Qwik components. In addition to Markdown syntax, `.mdx` files can also refer to other components. Let's assume you have your routes set up like this: + ``` - src/ - routes/ @@ -67,4 +68,8 @@ export const Counter = component$(() => { ); }); -``` \ No newline at end of file +``` + +**Note**: A key difference with Qwik City and many current metaframeworks is directory-based routing. Every route needs to be defined as `a-directory/index.(tsx,ts,js,jsx,md,mdx)`. + +In other metaframeworks you're used to `about.mdx` will render a route `http://example.com/about`. However, this will not work in Qwik City. You must rename the file to `about/index.mdx` for Qwik City to know to render it. \ No newline at end of file diff --git a/packages/docs/src/routes/qwikcity/content/menu/index.mdx b/packages/docs/src/routes/qwikcity/content/menu/index.mdx index 8f19bb6d68c..b1de8e263be 100644 --- a/packages/docs/src/routes/qwikcity/content/menu/index.mdx +++ b/packages/docs/src/routes/qwikcity/content/menu/index.mdx @@ -4,10 +4,10 @@ title: Qwik City - Menu # Qwik City - Menu -Menus allow you to describe the site navigation structure in a simple declarative way. Menus come in two parts: +Menus allow you to describe the site navigation structure in a simple declarative way. Menus come in two steps: -1. A `menu.md` file that contains the menu structure for the directory it's in. -2. A `useContent()` function that can be used to retrieve the menu structure in a template to be used for rendering. +1. Defining a `menu.md` file that contains the menu structure for the directory it's in. +2. Using the `useContent()` function to retrieve the menu structure in a template for rendering. [Read more here](/qwikcity/api/use-content) ## File Structure diff --git a/packages/docs/src/routes/qwikcity/endpoint/overview/index.mdx b/packages/docs/src/routes/qwikcity/endpoint/overview/index.mdx deleted file mode 100644 index d72fabfd8f9..00000000000 --- a/packages/docs/src/routes/qwikcity/endpoint/overview/index.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Qwik City - Endpoints ---- - -# Qwik City - Endpoints - -Endpoints are URLs that can be used to retrieve data, redirect users, or otherwise modify the response. - -Imagine that you have `https://example.com/product/abc123/details` and you want to get the details of the product with the id `abc123`. You can retrieve the data in two different ways: -1. As HTML for human consumption. -2. As JSON for machine consumption. - -In both cases, you are retrieving using the same URL `https://example.com/product/abc123/details`, the difference is the `Accept:` request header. -- `Accept: text/html`: retrieves HTML for human consumption -- `Accept: application/json`: retrieves JSON for machine consumption -- Perhaps some other serialization format in the future. - -In both cases, the logical content of the data retrieved is the same only the formatting is different. - -So far we have been talking about components that render static HTML. But what if the component needs data so that it can render it. How do we get the data? Additionally, when rendering on the server we would like to get the data directly, whereas when rendering on the client we would like to get the data from the server in JSON format. A different way to look at it is that the HTML internally retrieves the data from the JSON and then formats it for human consumption. - -Endpoints solve the above problem. Endpoints are a way of structuring data retrieval so that it can be used for both servers as well as client rendering inside components. \ No newline at end of file diff --git a/packages/docs/src/routes/qwikcity/menu.md b/packages/docs/src/routes/qwikcity/menu.md index ebd6afa114c..33451f1a56d 100644 --- a/packages/docs/src/routes/qwikcity/menu.md +++ b/packages/docs/src/routes/qwikcity/menu.md @@ -10,8 +10,12 @@ - [Overview](routing/overview/index.mdx) - [Index](routing/default-index/index.mdx) -- [Route Parameters](routing/route-parameters/index.mdx) - [Pathless Dirs](routing/pathless/index.mdx) +- [Route Parameters](routing/route-parameters/index.mdx) +- [Retrieving Data](endpoint/data/index.mdx) +- [Modifying Data](endpoint/modify/index.mdx) +- [Redirects](endpoint/redirects/index.mdx) +- [Error Responses](endpoint/error-responses/index.mdx) ## Layout @@ -26,13 +30,6 @@ - [MDX](content/mdx/index.mdx) - [Menu](content/menu/index.mdx) -## Data Endpoints - -- [Overview](endpoint/overview/index.mdx) -- [Retrieving Data](endpoint/data/index.mdx) -- [Modifying Data](endpoint/modify/index.mdx) -- [Non 200 Responses](endpoint/non-200/index.mdx) - ## Head - [Title](head/title/index.mdx) diff --git a/packages/docs/src/routes/qwikcity/endpoint/data/index.mdx b/packages/docs/src/routes/qwikcity/routing/data/index.mdx similarity index 86% rename from packages/docs/src/routes/qwikcity/endpoint/data/index.mdx rename to packages/docs/src/routes/qwikcity/routing/data/index.mdx index dc9d8914133..06eba682dfd 100644 --- a/packages/docs/src/routes/qwikcity/endpoint/data/index.mdx +++ b/packages/docs/src/routes/qwikcity/routing/data/index.mdx @@ -18,11 +18,11 @@ The first step is to structure the directories and files so that we can create t - index.tsx # https://example.com/product/1234 ``` -## Implement Endpoint +## Implement onGet -An endpoint is a `onGet` function that retrieves data (typically from a database, or other stores.) The retrieved data can be returned directly as JSON or used as an input to the component to render HTML. The `onGet` function receives the `params` to extract the parameters used to do data lookup. +In a "page" endpoint context, an `onGet` function retrieves data (typically from a database, or other stores). The retrieved data can be returned directly as JSON or used as an input to the component to render HTML. The `onGet` function receives the `params` to extract the parameters used to do data lookup. -The `onGet` function returns the product data. +In this example the `onGet` function returns the product data that is used inside of our component with the `useEndpoint()` function. ```typescript // File: src/routes/product/[skuId]/details.js @@ -44,7 +44,7 @@ export const onGet: RequestHandler = async ({ params }) => { }; ``` -## Using Endpoint in Component +## Using onGet in a Component An endpoint `onGet` function retrieves data and makes it available to the component using `useEndpoint()`. @@ -83,3 +83,4 @@ export default component$(() => { 6. You may use `typeof onGet` to keep your `onGet` function and `useEndpoint()` types in sync. Qwik City is smart enough to determine the types for you. All of the above is done to abstract the data access from the component in a way that results in correct behavior on both the server and the client. + diff --git a/packages/docs/src/routes/qwikcity/routing/default-index/index.mdx b/packages/docs/src/routes/qwikcity/routing/default-index/index.mdx deleted file mode 100644 index a9f6f408003..00000000000 --- a/packages/docs/src/routes/qwikcity/routing/default-index/index.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Qwik City - Default Index ---- - -# Qwik City - Default Index -### `index.tsx` / `index.mdx` - -Sometimes the route component gets too complex, and placing the whole implementation into a single file becomes impractical. In such a case, there is an alternative way to declare the same path. - -``` -- src/ - - routes/ - - index.tsx # https://example.com/ - - some/ - - index.tsx # https://example.com/some - - path/ - - index.tsx # https://example.com/some/path - - _other_component.tsx # this file is ignored and not mapped to any URL because of the leading underscore. -``` - -### `_` prefix - -Occasionally, there is a need to place files into the `src/routes` folder without them showing up on any route. In this case, use the `_` prefix to let Qwik City know that the file is private and should not be exposed. diff --git a/packages/docs/src/routes/qwikcity/routing/endpoints/index.mdx b/packages/docs/src/routes/qwikcity/routing/endpoints/index.mdx new file mode 100644 index 00000000000..88dc3cb84f4 --- /dev/null +++ b/packages/docs/src/routes/qwikcity/routing/endpoints/index.mdx @@ -0,0 +1,25 @@ +--- +title: Endpoints +--- + +# Endpoints + +As we discussed previously, an endpoint in Qwik City is `folders + an index`. + +For `index.md` and `index.mdx` files ((more here)[/qwikcity/content/mdx]), these endpoints will just return HTML and nothing else. For this section, we will focus on index.ts and index.tsx endpoints. + +## Page & Data Endpoints + +In Qwik City, "Page" and "Data" endpoints are the same except for one difference: a page exports a default component$ to render html. To learn about defining a page component, you can (read more here)[qwikcity/content/component]. A quick example would look like this: + +```typescript +// File: src/routes/some/path/index.tsx +import { component$ } from '@builder.io/qwik'; + +// Notice the default export +export default component$(() => { + return

Hello World!

; +}); +``` + +In the following sections, we'll look at the other things we can do within endpoint files. \ No newline at end of file diff --git a/packages/docs/src/routes/qwikcity/routing/error-responses/index.mdx b/packages/docs/src/routes/qwikcity/routing/error-responses/index.mdx new file mode 100644 index 00000000000..8a2b24eb480 --- /dev/null +++ b/packages/docs/src/routes/qwikcity/routing/error-responses/index.mdx @@ -0,0 +1,70 @@ +--- +title: Qwik City - Non-200 Response +--- + +# Qwik City - Non-200 Response + +At times it is necessary to respond with HTTP status codes other than 200. In such cases, response handler is the place to determine what status code should be returned. + +Assume this file layout. +``` +- src/ + - routes/ + - product/ + - [skuId]/ + - index.tsx # https://example.com/product/1234 +``` + +## 404 - Not Found + +Let's say that a user does a request to an invalid `skuId` such as `https://example.com/product/999`. In this case, we would like to return a 404 HTTP status code and render a 404 page. The place where we determine if the request is valid or not is in the request handler by looking into the database. Even if the response is non-200, the component still gets a chance to render a page (Except in the redirect case.) + +```typescript +// File: src/routes/product/[skuId]/index.tsx +import { component$ } from '@builder.io/qwik'; + +type EndpointData = ProductData | null; + +interface ProductData { + skuId: string; + price: number; + description: string; +} +export const onGet: RequestHandler = async ({ params, response }) => { + const product = await loadProductFromDatabase(params.skuId); + + if (!product) { + // Product data not found + // but the data is still given to the renderer to decide what to do + response.status = 404 + return null + } else { + // ... + } +}; + +export default component$(() => { + const resource = useEndpoint(); //equivalent to useEndpoint + + if (resource.state=='resolved' && !resource.resolved) { + // Early return for 404 + return
404: Product not found!!!
+ } + + // Normal rendering + return ( +
Loading...
} + onError={() =>
Error
} + onResolved={() => ( + <> +

Product: {product.productId}

+

Price: {product.price}

+

{product.description}

+ + )} + /> + ); +}); +``` \ No newline at end of file diff --git a/packages/docs/src/routes/qwikcity/endpoint/modify/index.mdx b/packages/docs/src/routes/qwikcity/routing/modify/index.mdx similarity index 71% rename from packages/docs/src/routes/qwikcity/endpoint/modify/index.mdx rename to packages/docs/src/routes/qwikcity/routing/modify/index.mdx index 10547952c85..d3691cb239f 100644 --- a/packages/docs/src/routes/qwikcity/endpoint/modify/index.mdx +++ b/packages/docs/src/routes/qwikcity/routing/modify/index.mdx @@ -4,9 +4,7 @@ title: Qwik City - Modify Data # Qwik City - Modify Data -> NOTE: Not yet implemented. - -Just like routes can define a way to fetch data, they can also define HTTP verbs to modify data. These are `GET`, `POST`, `PUT`, `PATCH`, `DELETE`. We have already discussed the `GET` verb in the previous section. Each of these verbs has a corresponding `on___` method such as `onGet`, `onPost`, `onPut`, `onPatch`, and `onDelete`. +Endpoints can define a way to fetch data and they can also define HTTP verbs to modify data. These are `GET`, `POST`, `PUT`, `PATCH`, `DELETE`. We have already discussed the `GET` verb in the previous section. Each of these verbs has a corresponding `on___` method such as `onGet`, `onPost`, `onPut`, `onPatch`, and `onDelete`. ```typescript // File: src/routes/product/[skuId]/index.tsx diff --git a/packages/docs/src/routes/qwikcity/routing/overview/index.mdx b/packages/docs/src/routes/qwikcity/routing/overview/index.mdx index dcf312a29a3..60aaff4f5e2 100644 --- a/packages/docs/src/routes/qwikcity/routing/overview/index.mdx +++ b/packages/docs/src/routes/qwikcity/routing/overview/index.mdx @@ -4,24 +4,74 @@ title: Qwik City - Routing # Qwik City - Routing -Routing is a way to map public URLs for a site to specific components declared in your application. Qwik City uses file-based routing. This means that the directory/file structure drives the public-facing URLs that the user will see for your application. +Routing is a way to map public URLs for a site to specific components declared in your application. -## Basic routing +Qwik City uses directory-based routing. This means that the structure of your routes directory drives the public-facing URLs that the user will see for your application. However, it differs slightly from traditional file based routing, which we will discuss shortly. -In the Qwik City routes directory, folders map to paths. For example, if the user sees `https://example.com/some/path`, the component exported at `src/routes/some/path` (either `.mdx` or `.tsx`) will be shown. + +## Directory Based Routing + +Qwik City support the follwing filetypes for routes + +In the Qwik City routes directory, `folders + an index` file map to a URL path. For example, if the user sees `https://example.com/some/path`, the component exported at `src/routes/some/path/index` (either `.mdx` or `.tsx`) will be shown. + +``` +- src/ + - routes/ + - some/ + - path/ + - index.tsx # https://example.com/some/path +``` + +Note that the leaf file at the end of the route named index. This is **important**. In other meta-frameworks you may be familiar with, there is a distinction made between `pages` and `data endpoints` or `api routes`. In Qwik City, there is no distinction, they are all `endpoints`. + +To define an endpoint, you must a define an `index.[filetype]` where [filetype] can be one of: + +While the following directory structure: ``` - src/ - routes/ + - contact.tsx + - about.tsx + - store.tsx + - index.tsx +``` + +may work in other meta-frameworks that use file based routing, Qwik City will not register a route for any non-index files. In Qwik City, the equivalent file structure would looks like this: + +``` +- src/ + - routes/ + - contact/ + - index.tsx + - about/ + - index.tsx + - store/ + - index.tsx + - index/ + - index.tsx +``` + +At first this may seem like extra work, but there are advantages to this approach. One advantage is being able define component files in a route directory without them being rendered. Consider the follwing: + +``` +- src/ + - routes/ + - index.tsx # https://example.com/ - some/ - - path.tsx # https://example.com/some/path + - index.tsx # https://example.com/some + - path/ + - index.tsx # https://example.com/some/path + - other_component.tsx # this file is ignored and not mapped to any URL because it is not an index. ``` +The `other_component.tsx` file can be imported and used inside of `path/index.tsx`, but is otherwise ignored by Qwik City. + ## Implementing a Component To return HTML for a specific route you will need to implement a component. For `.tsx` files the component must be exported as `default`. Alternatively, you can use `.mdx` extension discussed [later](/qwikcity/content/mdx). - ```typescript export default component$(() => { return ( @@ -32,10 +82,6 @@ export default component$(() => { }); ``` -### `_` prefix - -Occasionally, there is a need to place files into the `src/routes` folder without them showing up on any route. In this case, use the `_` prefix to let Qwik City know that the file is private and should not be exposed. - ## `@qwik-city-plan` Qwik City stores route information in files on disk. This is great for developer ergonomics but not useful for creating bundles and chunks. Additionally, in some environments - such as edge functions - there is no file system that can be accessed. For this reason, it is necessary to serialize the route information into a single file. This is done through the `@qwik-city-plan` import. @@ -49,10 +95,8 @@ The `@qwik-city-plan` import is synthetic, meaning that it is created as part of ## Advanced routing Qwik City also supports: -- [`index.tsx`](/qwikcity/routing/default-index) - [Route Parameters](/qwikcity/routing/route-parameters) -- [Pathless URLs](/qwikcity/routing/pathless) - [Nested layouts](/qwikcity/layout/overview) - [Menus](/qwikcity/content/menu) -These are discussed later. +These are discussed later. \ No newline at end of file diff --git a/packages/docs/src/routes/qwikcity/routing/pathless/index.mdx b/packages/docs/src/routes/qwikcity/routing/pathless/index.mdx index 94946f02ab1..07b5eccd225 100644 --- a/packages/docs/src/routes/qwikcity/routing/pathless/index.mdx +++ b/packages/docs/src/routes/qwikcity/routing/pathless/index.mdx @@ -4,14 +4,14 @@ title: Qwik City - Pathless # Qwik City - Pathless -At times components get so complex that using `index.ts` is not enough, and they need their own directory structure. In that case, Qwik City allows you to place the component into its own directory prefixed with `_`. Qwik City will then not use that directory name in the user URL. +At times components get so complex that using `index.ts` is not enough, and they need their own directory structure. In that case, Qwik City allows you to place the component into its own directory prefixed with `__`. Qwik City will then not use that directory name in the user URL. ``` - src/ - routes/ - some/ - path/ - - _complex-component/ # Notice the underscore prefix + - __complex-component/ # Notice the double underscore prefix - index.tsx # https://example.com/some/path (the _complex-component folder is ignored) - - _other_component.tsx # this file is ignored and not mapped to any URL because of the leading underscore. + - other_component.tsx # this file is ignored and not mapped to any URL because of the leading underscore. ``` diff --git a/packages/docs/src/routes/qwikcity/endpoint/non-200/index.mdx b/packages/docs/src/routes/qwikcity/routing/redirects/index.mdx similarity index 51% rename from packages/docs/src/routes/qwikcity/endpoint/non-200/index.mdx rename to packages/docs/src/routes/qwikcity/routing/redirects/index.mdx index 6fce630930a..638a7abc0c5 100644 --- a/packages/docs/src/routes/qwikcity/endpoint/non-200/index.mdx +++ b/packages/docs/src/routes/qwikcity/routing/redirects/index.mdx @@ -1,75 +1,8 @@ --- -title: Qwik City - Non-200 Response +title: Qwik City - Redirects --- -# Qwik City - Non-200 Response - -At times it is necessary to respond with HTTP status codes other than 200. In such cases, response handler is the place to determine what status code should be returned. - -Assume this file layout. -``` -- src/ - - routes/ - - product/ - - [skuId]/ - - index.tsx # https://example.com/product/1234 -``` - -## 404 - Not Found - -Let's say that a user does a request to an invalid `skuId` such as `https://example.com/product/999`. In this case, we would like to return a 404 HTTP status code and render a 404 page. The place where we determine if the request is valid or not is in the request handler by looking into the database. Even if the response is non-200, the component still gets a chance to render a page (Except in the redirect case.) - -```typescript -// File: src/routes/product/[skuId]/index.tsx -import { component$ } from '@builder.io/qwik'; - -type EndpointData = ProductData | null; - -interface ProductData { - skuId: string; - price: number; - description: string; -} -export const onGet: RequestHandler = async ({ params, response }) => { - const product = await loadProductFromDatabase(params.skuId); - - if (!product) { - // Product data not found - // but the data is still given to the renderer to decide what to do - response.status = 404 - return null - } else { - // ... - } -}; - -export default component$(() => { - const resource = useEndpoint(); //equivalent to useEndpoint - - if (resource.state=='resolved' && !resource.resolved) { - // Early return for 404 - return
404: Product not found!!!
- } - - // Normal rendering - return ( -
Loading...
} - onError={() =>
Error
} - onResolved={() => ( - <> -

Product: {product.productId}

-

Price: {product.price}

-

{product.description}

- - )} - /> - ); -}); -``` - -## 3xx - Redirect +# Qwik City - Redirects Sometimes you want to redirect a user from the current page to another page.