Skip to main content

Complex Params

Atom params and atom selector params must be serializable (with the exception of passing atom instances themselves). Though it isn't recommended, you can disable this requirement.

you will learn

How to make Zedux map non-serializable objects to serializable ids when creating atom instance and atom selector ids.

complexParams

This ecosystem config option turns on param mapping for atom and atom selector params.

const ecosystem = createEcosystem({
complexParams: true,
id: 'root',
})
// or
<EcosystemProvider complexParams id="root">
{children}
</EcosystemProvider>

An example passing a filter function as an atom param:

Live Sandbox
123456789101112131415161718192021
const numbers = Array(10)
.fill()
.map((_, i) => i)

const numbersAtom = atom('numbers', filter => numbers.filter(filter))

const ecosystem = createEcosystem({
complexParams: true,
id: 'atom-params-example',
})

const evenNumbersInstance = ecosystem.getInstance(numbersAtom, [
num => !(num % 2),
])

const oddNumbersInstance = ecosystem.getInstance(numbersAtom, [num => num % 2])

const output = {
evenNumbers: evenNumbersInstance.getState(),
oddNumbers: oddNumbersInstance.getState(),
}

An example with atom selectors:

Live Sandbox
12345678910111213141516171819202122232425262728293031
const colorsAtom = atom('colors', () => [
{ name: 'azure', base: 'blue' },
{ name: 'navy', base: 'blue' },
{ name: 'burgundy', base: 'red' },
])

// an atom selector:
const getByFilter = ({ get }, filter) => get(colorsAtom).filter(filter)

// a nice helper function we made
const filterByBlues = item => item.base === 'blue'

function Blues() {
// the `filterByBlues` param isn't serializable but we can pass it now thanks
// to `complexParams`:
const blues = useAtomSelector(getByFilter, filterByBlues)

return (
<ul>
{blues.map(item => (
<li key={item.name}>{item.name}</li>
))}
</ul>
)
}

const App = () => (
<EcosystemProvider complexParams id="blues">
<Blues />
</EcosystemProvider>
)

Try clicking Log > Graph to see that Zedux generated an id for the getByFilter atom selector node's param.

Referential Equality

Typically you should extract the complex param into a separate variable so it can be shared across usages:

// these calls create different instances since the function reference changes:
getInstance(numbersAtom, [num => num % 2])
getInstance(numbersAtom, [num => num % 2])

// declare the function separately so it can be reused:
const getEvenNumbers = num => num % 2

// now these calls reuse the same instance:
getInstance(numbersAtom, [getEvenNumbers])
getInstance(numbersAtom, [getEvenNumbers])

Why not?

Using complex params is not recommended because the ids that Zedux generates can make your atom graph more difficult to read and debug. When working with multiple windows or realms of any sort, it also requires more work on your part to share object references across the realms so Zedux can recognize them.