web/versioned_docs/version-0.22/project/client-config.md
import BaseDirEnvNote from './_baseDirEnvNote.md'
import { ShowForTs, ShowForJs } from '@site/src/components/TsJsHelpers'
You can configure the client using the client field inside the app declaration:
Wasp gives you the option to define a "wrapper" component for your React app.
It can be used for a variety of purposes, but the most common ones are:
Let's define a common layout for your application:
<Tabs groupId="js-ts"> <TabItem value="js" label="JavaScript"> ```wasp title="main.wasp" app MyApp { title: "My app", // ... client: { rootComponent: import Root from "@src/Root", } } ``````jsx title="src/Root.jsx"
import { Outlet } from 'react-router'
export default function Root() {
return (
<div>
<header>
<h1>My App</h1>
</header>
// highlight-next-line
<Outlet />
<footer>
<p>My App footer</p>
</footer>
</div>
)
}
```
```tsx title="src/Root.tsx"
import { Outlet } from 'react-router'
export default function Root() {
return (
<div>
<header>
<h1>My App</h1>
</header>
// highlight-next-line
<Outlet />
<footer>
<p>My App footer</p>
</footer>
</div>
)
}
```
You need to import the Outlet component from react-router and put it where you want the current page to be rendered.
This is how to set up various providers that your application needs:
<Tabs groupId="js-ts"> <TabItem value="js" label="JavaScript"> ```wasp title="main.wasp" app MyApp { title: "My app", // ... client: { rootComponent: import Root from "@src/Root", } } ``````jsx title="src/Root.jsx"
import { Outlet } from 'react-router'
import store from './store'
import { Provider } from 'react-redux'
export default function Root() {
return (
<Provider store={store}>
<Outlet />
</Provider>
)
}
```
```tsx title="src/Root.tsx"
import { Outlet } from 'react-router'
import store from './store'
import { Provider } from 'react-redux'
export default function Root() {
return (
<Provider store={store}>
<Outlet />
</Provider>
)
}
```
As long as you render the Outlet component, you can put what ever you want in the root component.
Read more about the root component in the API Reference.
setupFn declares a <ShowForTs>Typescript</ShowForTs><ShowForJs>JavaScript</ShowForJs> function that Wasp executes on the client before everything else.
We can run any code we want in the setup function.
For example, here's a setup function that logs a message every hour:
<Tabs groupId="js-ts"> <TabItem value="js" label="JavaScript"> ```js title="src/myClientSetupCode.js" export default async function mySetupFunction() { let count = 1 setInterval( () => console.log(`You have been online for ${count++} hours.`), 1000 * 60 * 60 ) } ``` </TabItem> <TabItem value="ts" label="TypeScript"> ```ts title="src/myClientSetupCode.ts" export default async function mySetupFunction(): Promise<void> { let count = 1 setInterval( () => console.log(`You have been online for ${count++} hours.`), 1000 * 60 * 60 ) } ``` </TabItem> </Tabs>:::info
You can change the options for a single Query using the options object, as described here.
:::
Wasp's useQuery hook uses react-query's useQuery hook under the hood. Since react-query comes configured with aggressive but sane default options, you most likely won't have to change those defaults for all Queries.
If you do need to change the global defaults, you can do so inside the client setup function.
Wasp exposes a configureQueryClient hook that lets you configure react-query's QueryClient object:
export default async function mySetupFunction() {
// ... some setup
configureQueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
},
})
// ... some more setup
}
```
export default async function mySetupFunction(): Promise<void> {
// ... some setup
configureQueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
},
})
// ... some more setup
}
```
Make sure to pass in an object expected by the QueryClient's constructor, as
explained in
react-query's docs.
Read more about the setup function in the API Reference.
If you need to serve the client from a subdirectory, you can use the baseDir option:
app MyApp {
title: "My app",
// ...
client: {
baseDir: "/my-app",
}
}
This means that if you serve your app from https://example.com/my-app, the
router will work correctly, and all the assets will be served from
https://example.com/my-app.
Client has the following options:
rootComponent: ExtImportrootComponent defines the root component of your client application. It is
expected to be a React component, and Wasp will use it as the root of the
client application.
It must render the Outlet component from react-router to render the
current page.
Here's an example of a root component that both sets up a provider and renders a custom layout:
<Tabs groupId="js-ts"> <TabItem value="js" label="JavaScript"> ```jsx title="src/Root.jsx" import { Outlet } from 'react-router' import store from './store' import { Provider } from 'react-redux'export default function Root() {
return (
<Provider store={store}>
<Layout />
</Provider>
)
}
function Layout() {
return (
<div>
<header>
<h1>My App</h1>
</header>
// highlight-next-line
<Outlet />
<footer>
<p>My App footer</p>
</footer>
</div>
)
}
```
export default function Root() {
return (
<Provider store={store}>
<Layout />
</Provider>
)
}
function Layout() {
return (
<div>
<header>
<h1>My App</h1>
</header>
// highlight-next-line
<Outlet />
<footer>
<p>My App footer</p>
</footer>
</div>
)
}
```
setupFn: ExtImportYou can use this function to perform any custom setup (e.g., setting up client-side periodic jobs).
<Tabs groupId="js-ts"> <TabItem value="js" label="JavaScript"> ```js title="src/myClientSetupCode.js" export default async function mySetupFunction() { // Run some code } ``` </TabItem> <TabItem value="ts" label="TypeScript"> ```ts title="src/myClientSetupCode.ts" export default async function mySetupFunction(): Promise<void> { // Run some code } ``` </TabItem> </Tabs>baseDir: StringIf you need to serve the client from a subdirectory, you can use the baseDir option.
If you set baseDir to /my-app for example, that will make Wasp set the basename prop of the Router to
/my-app. It will also set the base option of the Vite config to /my-app.
This means that if you serve your app from https://example.com/my-app, the router will work correctly, and all the assets will be served from https://example.com/my-app.