Client Config
You can configure the client using the client field inside the app declaration:
- JavaScript
- TypeScript
appMyApp{
title: "My app",
// ...
client: {
rootComponent: importRootfrom"@src/Root",
setupFn: importmySetupFunctionfrom"@src/myClientSetupCode"
}
}
appMyApp{
title: "My app",
// ...
client: {
rootComponent: importRootfrom"@src/Root",
setupFn: importmySetupFunctionfrom"@src/myClientSetupCode"
}
}
Root Componentβ
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:
- Defining a common layout for your application.
- Setting up various providers that your application needs.
Defining a Common Layoutβ
Let's define a common layout for your application:
- JavaScript
- TypeScript
appMyApp{
title: "My app",
// ...
client: {
rootComponent: importRootfrom"@src/Root",
}
}
import{Outlet}from'react-router-dom'
exportdefaultfunctionRoot(){
return(
<div>
<header>
<h1>My App</h1>
</header>
<Outlet/>
<footer>
<p>My App footer</p>
</footer>
</div>
)
}
appMyApp{
title: "My app",
// ...
client: {
rootComponent: importRootfrom"@src/Root",
}
}
import{Outlet}from'react-router-dom'
exportdefaultfunctionRoot(){
return(
<div>
<header>
<h1>My App</h1>
</header>
<Outlet/>
<footer>
<p>My App footer</p>
</footer>
</div>
)
}
You need to import the Outlet component from react-router-dom and put it where you want the current page to be rendered.
Setting up a Providerβ
This is how to set up various providers that your application needs:
- JavaScript
- TypeScript
appMyApp{
title: "My app",
// ...
client: {
rootComponent: importRootfrom"@src/Root",
}
}
import{Outlet}from'react-router-dom'
importstorefrom'./store'
import{Provider}from'react-redux'
exportdefaultfunctionRoot(){
return(
<Providerstore={store}>
<Outlet/>
</Provider>
)
}
appMyApp{
title: "My app",
// ...
client: {
rootComponent: importRootfrom"@src/Root",
}
}
import{Outlet}from'react-router-dom'
importstorefrom'./store'
import{Provider}from'react-redux'
exportdefaultfunctionRoot(){
return(
<Providerstore={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.
Setup Functionβ
setupFn declares a function that Wasp executes on the client before everything else.
Running Some Codeβ
We can run any code we want in the setup function.
For example, here's a setup function that logs a message every hour:
- JavaScript
- TypeScript
exportdefaultasyncfunctionmySetupFunction(){
let count =1
setInterval(
()=>console.log(`You have been online for ${count++} hours.`),
1000*60*60
)
}
exportdefaultasyncfunctionmySetupFunction():Promise<void>{
let count =1
setInterval(
()=>console.log(`You have been online for ${count++} hours.`),
1000*60*60
)
}
Overriding Default Behaviour for Queriesβ
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:
- JavaScript
- TypeScript
import{ configureQueryClient }from'wasp/client/operations'
exportdefaultasyncfunctionmySetupFunction(){
// ... some setup
configureQueryClient({
defaultOptions:{
queries:{
staleTime:Infinity,
},
},
})
// ... some more setup
}
import{ configureQueryClient }from'wasp/client/operations'
exportdefaultasyncfunctionmySetupFunction():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.
Base Directoryβ
If you need to serve the client from a subdirectory, you can use the baseDir option:
appMyApp{
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.
If you set the baseDir option, make sure that the WASP_WEB_CLIENT_URL env variable also includes that base directory.
For example, if you are serving your app from https://example.com/my-app, the WASP_WEB_CLIENT_URL should be also set to https://example.com/my-app, and not just https://example.com.
API Referenceβ
- JavaScript
- TypeScript
appMyApp{
title: "My app",
// ...
client: {
rootComponent: importRootfrom"@src/Root",
setupFn: importmySetupFunctionfrom"@src/myClientSetupCode"
}
}
appMyApp{
title: "My app",
// ...
client: {
rootComponent: importRootfrom"@src/Root",
setupFn: importmySetupFunctionfrom"@src/myClientSetupCode",
baseDir: "/my-app",
}
}
Client has the following options:
-
rootComponent: ExtImportβrootComponentdefines 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 theOutletcomponent fromreact-router-domto render the current page.Here's an example of a root component that both sets up a provider and renders a custom layout:
- JavaScript
- TypeScript
src/Root.jsximport{Outlet}from'react-router-dom'
importstorefrom'./store'
import{Provider}from'react-redux'
exportdefaultfunctionRoot(){
return(
<Providerstore={store}>
<Layout/>
</Provider>
)
}
functionLayout(){
return(
<div>
<header>
<h1>My App</h1>
</header>
<Outlet/>
<footer>
<p>My App footer</p>
</footer>
</div>
)
}src/Root.tsximport{Outlet}from'react-router-dom'
importstorefrom'./store'
import{Provider}from'react-redux'
exportdefaultfunctionRoot(){
return(
<Providerstore={store}>
<Layout/>
</Provider>
)
}
functionLayout(){
return(
<div>
<header>
<h1>My App</h1>
</header>
<Outlet/>
<footer>
<p>My App footer</p>
</footer>
</div>
)
} -
setupFn: ExtImportβYou can use this function to perform any custom setup (e.g., setting up client-side periodic jobs).
- JavaScript
- TypeScript
src/myClientSetupCode.jsexportdefaultasyncfunctionmySetupFunction(){
// Run some code
}src/myClientSetupCode.tsexportdefaultasyncfunctionmySetupFunction():Promise<void>{
// Run some code
} -
baseDir: StringβIf you need to serve the client from a subdirectory, you can use the
baseDiroption.If you set
baseDirto/my-appfor example, that will make Wasp set thebasenameprop of theRouterto/my-app. It will also set thebaseoption 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 fromhttps://example.com/my-app.Setting the correct env variableIf you set the
baseDiroption, make sure that theWASP_WEB_CLIENT_URLenv variable also includes that base directory.For example, if you are serving your app from
https://example.com/my-app, theWASP_WEB_CLIENT_URLshould be also set tohttps://example.com/my-app, and not justhttps://example.com.