Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: improve eslint loader msg + add cookbook example #5591

Merged
merged 18 commits into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/docs/src/routes/docs/(qwikcity)/action/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ contributors:
- aivarsliepa
- wtlin1228
- adamdbradley
updated_at: '2023-10-03T18:53:23Z'
- gioboa
updated_at: '2023-12-15T11:00:00Z'
created_at: '2023-03-20T23:45:13Z'
---

Expand Down Expand Up @@ -394,6 +395,8 @@ We recommend starting with `routeAction$()` and only use `globalAction$()` when

`routeAction$()` can only be declared inside the `src/routes` folder, in a `layout.tsx` or `index.tsx` file, and they MUST be exported, just like a `routeLoader$()`. Since `routeAction$()`s are only accessible within the route it's declared, they are recommended when the action needs to access some user data, or it's a protected route. Think about it like a "private" action.

> If you want to manage common reusable routeAction$() it is important that this function is re-exported from within 'layout.tsx' or 'index.tsx file of the existing route otherwise it will not run or throw exception. For more information [check the cookbook](/docs/cookbook/re-exporting-loaders/index.mdx).

```tsx title="src/routes/form/index.tsx"
import { routeAction$ } from '@builder.io/qwik-city';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ contributors:
- mrhoodz
- mjschwanitz
- adamdbradley
updated_at: '2023-09-15T11:23:15Z'
- gioboa
updated_at: '2023-12-15T11:00:00Z'
created_at: '2023-03-20T23:45:13Z'
---

Expand All @@ -23,6 +24,8 @@ Route Loaders load data in the server so it becomes available to use inside Qwik

Route Loaders can only be declared inside the `src/routes` folder, in a `layout.tsx` or `index.tsx` file, and they MUST be exported.

> If you want to manage common reusable routeLoaders$ it is important that this function is re-exported from within 'layout.tsx' or 'index.tsx file of the existing route otherwise it will not run or throw exception. For more information [check the cookbook](/docs/cookbook/re-exporting-loaders/index.mdx).

```tsx /routeLoader$/ /useProductData/#a title="src/routes/product/[productId]/index.tsx"
import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
Expand Down
9 changes: 6 additions & 3 deletions packages/docs/src/routes/docs/cookbook/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ contributors:
- Craiqser
- Inaam-Ur-Rehman
- maiieul
updated_at: '2023-10-10T19:26:56Z'
- gioboa
updated_at: '2023-12-15T11:00:00Z'
created_at: '2023-08-14T18:24:46Z'
---

Expand All @@ -16,7 +17,9 @@ created_at: '2023-08-14T18:24:46Z'
A cookbook contains a collection of useful patterns for solving common problems in front-end development.

Examples:
- [Modal Dialog Pop-Up](./portal/)
- [Glob Import with import.meta.glob](./glob-import/)
- [Media Controller with iOS Support](./mediaController/)
- [Glob Import with `import.meta.glob`](./glob-import/)
- [Portal (Modal Dialog Pop-Up)](./portal/)
- [Re-exporting loaders](./re-exporting-loaders/)
- [Theme Managment](./theme-management/)

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: Cookbook | Re-exporting loaders
contributors:
- gioboa
updated_at: '2023-12-15T11:00:00Z'
created_at: '2023-12-15T11:00:00Z'
---

# Re-exporting loaders

`routeAction$` and `routeLoader$` are typically declared in route boundary files such as layout.tsx, index.tsx and plugin.tsx inside the routesDir directory
gioboa marked this conversation as resolved.
Show resolved Hide resolved
[here is docs](https://qwik.builder.io/docs/route-loader/).

Somethimes you would like to declared them outside of the route boundaries.
This may be useful when you want to create reusable logic or a library.
In such a case it is important that this function is re-exported from within the router boundary otherwise it will not run or throw exception.

## Solution

You can define `routeAction$` and `routeLoader$` in your custom path and re-export them in your layout.tsx, index.tsx and plugin.tsx files.

Example with this path `./src/shared/loaders.ts`

```tsx
import { routeAction$, routeLoader$ } from '@builder.io/qwik-city';

// eslint-disable-next-line qwik/loader-location
export const useCommonRouteAction = routeAction$(async () => {
// ...
});

// eslint-disable-next-line qwik/loader-location
export const useCommonRouteLoader = routeLoader$(async () => {
// ...
});
```
gioboa marked this conversation as resolved.
Show resolved Hide resolved
---
Now you can use your common `routeAction$` and `routeLoader$` in paths like this one `./src/routes/index.tsx`.

```tsx
import { component$ } from '@builder.io/qwik';
import { Form } from '@builder.io/qwik-city';
import { useCommonRouteAction, useCommonRouteLoader } from '../shared/loaders';

// As mentioned, here we are re-exporting them
export { useCommonRouteAction, useCommonRouteLoader } from '../shared/loaders';

export default component$(() => {
const commonRouteAction = useCommonRouteAction();
const commonRouteLoader = useCommonRouteLoader();

return (
<div>
<Form action={commonRouteAction}>
<button type='submit'>Submit</button>
</Form>
{commonRouteLoader.value}
</div>
);
});
```
2 changes: 2 additions & 0 deletions packages/docs/src/routes/docs/menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
- [Glob Import](/docs/cookbook/glob-import/index.mdx)
- [Media Controller](/docs/cookbook/mediaController/index.mdx)
- [Portal](/docs/cookbook/portal/index.mdx)
- [Re-exporting loaders](/docs/cookbook/re-exporting-loaders/index.mdx)
- [Theme Managment](/docs/cookbook/theme-management/index.mdx)

## Integrations

Expand Down
6 changes: 3 additions & 3 deletions packages/eslint-plugin-qwik/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
"peerDependencies": {
"eslint": "^8.45.0"
},
"scripts": {
"test": "cd ../..; ./node_modules/.bin/vitest packages/eslint-plugin-qwik/qwik.unit.ts"
},
"repository": {
"type": "git",
"url": "https://github.com/BuilderIO/qwik.git",
"directory": "packages/eslint-rules"
},
"scripts": {
"test": "cd ../..; ./node_modules/.bin/vitest packages/eslint-plugin-qwik/qwik.unit.ts"
}
}
11 changes: 9 additions & 2 deletions packages/eslint-plugin-qwik/src/loaderLocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,15 @@ export const loaderLocation: Rule.RuleModule = {
},
],
messages: {
invalidLoaderLocation:
'`{{fnName}}()` can only be declared in `layout.tsx`, `index.tsx` and `plugin.tsx` inside the {{routesDir}} directory, instead it was declared in "{{path}}".\nPlease check the docs: https://qwik.builder.io/docs/route-loader/',
invalidLoaderLocation: `'{{fnName}}() are typically declared in route boundary files such as layout.tsx, index.tsx and plugin.tsx inside the {{routesDir}} directory
(docs: https://qwik.builder.io/docs/route-loader/).

This {{fnName}}() is declared outside of the route boundaries. This may be useful when you want to create reusable logic or a library. In such a case it is important that this function is re-exported from within the router boundary otherwise it will not run.
(docs: https://qwik.builder.io/docs/cookbook/re-exporting-loaders/).

If you understand this, you can disable this warning with:
// eslint-disable-next-line qwik/loader-location
`,
missingExport:
'The return of `{{fnName}}()` needs to be exported in the same module, like this\n```\nexport const {{id}} = {{fnName}}(() => { ... });\n```',
wrongName:
Expand Down
5 changes: 4 additions & 1 deletion packages/qwik-city/runtime/src/server-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,10 @@ export const routeLoaderQrl = ((
if (!(id in state)) {
throw new Error(`routeLoader$ "${loaderQrl.getSymbol()}" was invoked in a route where it was not declared.
This is because the routeLoader$ was not exported in a 'layout.tsx' or 'index.tsx' file of the existing route.
For more information check: https://qwik.builder.io/qwikcity/route-loader/`);
For more information check: https://qwik.builder.io/qwikcity/route-loader/

If your are managing reusable logic or a library it is important that this function is re-exported from within 'layout.tsx' or 'index.tsx file of the existing route otherwise it will not run or throw exception.
gioboa marked this conversation as resolved.
Show resolved Hide resolved
For more information check: https://qwik.builder.io/docs/cookbook/re-exporting-loaders/.`);
}
return _wrapSignal(state, id);
});
Expand Down
Loading