Advanced Topics
note
Here are some more things you can do with Kea. You probably won't need use them, yet the information is here in case you do.
#
LifecyclesKea's logic
has three different states:
- Initialized. When your JavaScript interpreter encounters a
const logic = kea(input)
call, not much happens. It just stores theinput
variable on the logic and goes on. No processing takes place. - Built. When a logic is needed, it must first be built. This means converting
an
input
such as{ actions: { ... } }
into actual functions onlogic.actions
that can be called. Same for all thereducers
,selectors
, etc. - Mounted. Once a logic is built, it can be mounted. This means attaching the
reducers
to Redux, registering all thelisteners
, etc.
If you use Kea outside of React, you have to mount and unmount your logic
manually.
Read the next section for instructions on how to do so.
If you use Kea with React, every time you render a component that access a logic
via useValues
, useActions
or some other method, the logic is built and mounted automatically. When all components
that use a logic
are removed from React's tree, that logic
will be unmounted automatically.
Only logic
which is actively in use will be mounted and attached to Redux.
#
Mounting and UnmountingWhen you use Kea with React, there's a lot that is handled for you behind the scenes.
For example logic is mounted automatically with your <Component />
and unmounted when it's no longer needed.
Sometimes however, you wish to manually mount logic. For example to already start loading data in
your router before transitioning to a component... or in getInitialProps
in next.js... or when writing
tests with Jest.
Perhaps you even want to use Kea with a framework other than React.
In any case, just call mount()
on your logic and get as a reply a function that will unmount
it:
In case you need to pass props to your logic, for example if it is keyed,
you should build the logic explicitly before calling mount()
on it:
There are a few other options you can use. See the logic API for more details.
logic.mount()
inside listeners#
Calling In Kea 2.0 logic automatically connects when used inside another logic.
Assuming counterLogic
is not used anywhere else, when called in the listener here,
it will be automatically built and mounted:
It will also remain mounted for as long as logic
is mounted.
What if you don't want that and instead prefer to mount and unmount counerLogic
manually within
the listener?
A practical example of this is to mount a logic to preload data on a route change 150ms before transitioning the scene... and then to unmount it manually once the page loaded. It's enough to prevent the "flash of loading" in most cases.
Instead of directly calling logic.mount()
, you just need to build the logic fist, even if it
doesn't need any props. You must then pass false
as the second argument to .build
:
Instead of using logic(props)
to build the logic, use logic.build(props, false)
.
Without explicitly setting this second argument (autoConnectInListener
) to false,
counterLogic
would have been automatically built and mounted on counterLogic.values
.
Calling .mount()
on a built and mounted logic won't mount it twice, but it will stay mounted
until the returned unmount
is called, even if no other logic is connected to it.
#
Extending logicUp until a logic has been built and mounted, you can extend it:
Extending logic is especially powerful when writing plugins. For example to dynamically add actions, reducers or listeners to a logic, based on some key.
#
Props in SelectorsSince selectors
need to be recalculated when their inputs change, there's a twist when
using props
with them.
Take the following buggy code:
The code will work, but only partially.
The problem is that the value of diffFromDefault
will only be updated when counter
changes,
but not when props.defaultCounter
changes.
What if we would also like to update the selector when the props change?
Previously we defined a selector as a function like this:
That's an incomplete definition. All selectors have a second argument called props
.
To make your new selector update itself when props change, use an inline
selector that picks the right value from props
:
#
Shared listenersIf multiple listeners
need to run the same code, you can:
- Have all of them call a common action, which you then handle with another listener:
This however dispatches a separate action, which is then listened to.
- If you want to share code between listeners without dispatching another action, use
sharedListeners
:
That function will be called directly, without an action being dispatched in the middle.
You might still prefer to explicitly dispatch an action, as that level of abstraction may be better suited for the task at hand. You can use the shared action in a reducer for example.
Next steps
- For even more advanced topics, read Migrating from Redux to learn how Kea and Redux interact under the hood.