Skip to content
On this page

Query Params Sync

In this example, we will demonstrate how to use querySync

Task

Imagine that we have some search form.
And we want to update query whenever we change it.
We also want to fill the search field if we open this page with query passed.

Solution

Suppose that we have a search page with this model:

ts
// @/pages/search
import { createRoute } from 'atomic-router'
import { createEvent, createStore } from 'effector'

export const searchPageRoute = createRoute()

export const qChanged = createEvent<string>()

export const $q = createStore("")

$q.on(qChanged, (_, q) => q)

First of all, create router controls (if not yet created):

ts
// @/shared/routing
import { createRouterControls} 

export const controls = createRouterControls()

In order for controls.$query to work, we need to pass it to our router:

ts
// @/app/routing
import { createHistoryRouter } from 'atomic-router'
import { controls } from '@/shared/routing'

const routes = [/* ... */]

const router = createHistoryRouter({
  routes,
  controls
})

Now we can just use querySync method in our model:

ts
// @/pages/search
import { createRoute, querySync } from 'atomic-router'
import { createEvent, createStore } from 'effector'
import { controls } from '@/shared/routing'

export const searchPageRoute = createRoute()

export const qChanged = createEvent<string>()

export const $q = createStore("")

$q.on(qChanged, (_, q) => q)

querySync({
  source: { q: $q },
  route: searchPageRoute,
  controls
})

Edge-cases

Debounce

If we don't want to spam query updates, we can pass clock parameter.

Combined with patronum/debounce it'll look like this:

ts
// @/pages/search
import { debounce } from 'patronum'
import { createRoute, querySync } from 'atomic-router'
import { createEvent, createStore } from 'effector'
import { controls } from '@/shared/routing'

export const searchPageRoute = createRoute()

export const qChanged = createEvent<string>()

export const $q = createStore("")

$q.on(qChanged, (_, q) => q)

querySync({
  source: { q: $q },
  clock: debounce({ source: qChanged, timeout: 30 }),
  route: searchPageRoute,
  controls
})

This will update every 30ms

Keep empty parameters

If we want to keep q in query even if it's empty, we can use cleanup parameter

ts
// @/pages/search
import { debounce } from 'patronum'
import { createRoute, querySync } from 'atomic-router'
import { createEvent, createStore } from 'effector'
import { controls } from '@/shared/routing'

export const searchPageRoute = createRoute()

export const qChanged = createEvent<string>()

export const $q = createStore("")

$q.on(qChanged, (_, q) => q)

querySync({
  source: { q: $q },
  clock: debounce({ source: qChanged, timeout: 30 }),
  route: searchPageRoute,
  cleanup: {
    empty: false
    // or preserve: ['q']
  },
  controls
})