### Combined Kea Logic Example
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/key-props-path.md
Demonstrates a combined Kea logic setup including path, key, props, reducers, selectors, actions, and listeners. Use this for complex state management scenarios.
```typescript
const todoLogic = kea([
// Define where this exists in the state tree and how to identify instances
path(['scenes', 'todos']),
key((props) => props.listId),
props({ listId: 0 } as { listId: number }),
// Define the data and how to modify it
reducers({
todos: [[], { /* ... */ }],
filter: ['all', { /* ... */ }],
}),
// Define computed values
selectors({
filteredTodos: [
(s, p) => [s.todos, s.filter, p.listId],
(todos, filter, listId) => {
// filter todos...
return todos
}
],
}),
// Define actions
actions({
addTodo: (title: string) => ({ title }),
}),
// Listen to actions
listeners({
addTodo: ({ title }, breakpoint) => {
console.log('Added:', title)
},
}),
])
// Usage with props
const list = todoLogic({ listId: 1 })
list.mount()
```
--------------------------------
### afterMount() Usage Example
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/defaults-events.md
Demonstrates how to use the afterMount helper to execute logic after a Kea logic instance has been mounted. This example logs the logic's path and fetches data.
```typescript
const dataLogic = kea([
afterMount((logic) => {
console.log('Loading data for', logic.path)
fetch('/api/data').then(r => r.json()).then(console.log)
}),
])
```
--------------------------------
### Complete Kea Application Setup
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/context.md
Demonstrates a full application setup including context initialization with custom plugins and defaults, defining a logic with reducers and actions, mounting the logic, and accessing the global context.
```typescript
import { resetContext, getContext, kea, actions, reducers } from 'kea'
import customPlugin from './customPlugin'
// Initialize context with options
resetContext({
plugins: [customPlugin],
debug: true,
defaults: {
app: {
initialized: false,
},
},
})
// Define a logic
const appLogic = kea([
reducers({
initialized: [false, {
initApp: () => true,
}],
}),
actions({
initApp: () => null,
}),
])
// Mount logic and use
const logic = appLogic.build()
logic.mount()
// Access context
const ctx = getContext()
console.log(ctx.store.getState())
```
--------------------------------
### beforeUnmount() Usage Example
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/defaults-events.md
Demonstrates how to use the beforeUnmount helper to execute cleanup logic before a Kea logic instance is unmounted. This example logs a message and cancels pending requests.
```typescript
const listLogic = kea([
beforeUnmount((logic) => {
console.log('Cleaning up list')
cancelPendingRequests()
}),
])
```
--------------------------------
### Simple Listener Example
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/listeners.md
A basic example demonstrating how to define a listener for the `increment` action. This listener logs a message to the console when the action is dispatched.
```typescript
const counterLogic = kea([
actions({
increment: () => null,
}),
listeners({
increment: ({ payload }, breakpoint) => {
console.log('Count was incremented')
},
}),
])
```
--------------------------------
### Complete Kea Logic Example in React
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-hooks.md
A full example demonstrating how to define Kea logic (actions, reducers, selectors, listeners) and integrate it into a React component using Kea's React hooks.
```typescript
import { kea, actions, reducers, selectors, listeners } from 'kea'
import { useValues, useActions, useAsyncActions } from 'kea'
const todoLogic = kea([
actions({
addTodo: (title: string) => ({ title }),
removeTodo: (id: number) => ({ id }),
}),
reducers({
todos: [[], {
addTodo: (state, { title }) => [
...state,
{ id: Date.now(), title, done: false }
],
removeTodo: (state, { id }) =>
state.filter(todo => todo.id !== id),
}],
}),
selectors({
todosCount: [(s) => [s.todos], (todos) => todos.length],
}),
listeners({
addTodo: ({ title }, breakpoint) => {
console.log('Todo added:', title)
},
}),
])
function TodoApp() {
const { todos, todosCount } = todoLogic.useValues()
const { addTodo, removeTodo } = todoLogic.useActions()
const [input, setInput] = React.useState('')
const handleAdd = () => {
addTodo(input)
setInput('')
}
return (
setInput(e.target.value)}
/>
Todos: {todosCount}
{todos.map(todo => (
{todo.title}
))}
)
}
export default todoLogic.wrap(TodoApp)
```
--------------------------------
### Testing Configuration
Source: https://github.com/keajs/kea/blob/master/_autodocs/configuration.md
Set up Kea for testing environments, enabling store creation and applying test-specific defaults. Includes setup and teardown for contexts.
```typescript
// Before each test
resetContext({
createStore: true,
defaults: {
// test defaults
},
})
// After each test
closeContext()
```
--------------------------------
### Complete Kea React Application Example
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-components.md
Demonstrates a full React application using Kea for state management. It includes defining logic with actions and reducers, and integrating it into components using useValues and useActions.
```typescript
import React, { useState } from 'react'
import { kea, actions, reducers, selectors } from 'kea'
import { BindLogic, useValues, useActions } from 'kea'
// Define a logic
const postLogic = kea([
actions({
openPost: (id: number) => ({ id }),
closePost: () => null,
}),
reducers({
openPostId: [null as number | null, {
openPost: (_, { id }) => id,
closePost: () => null,
}],
}),
])
// Component using the logic
function PostDetail() {
const { openPostId } = postLogic.useValues()
const { closePost } = postLogic.useActions()
if (!openPostId) return null
return (
)
}
export default PostsApp
```
--------------------------------
### Selector Examples
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/selectors.md
Illustrates various ways to define and use selectors, including simple selectors, selectors with multiple inputs, selectors using props, connected selectors, custom memoization, complex computations, and selectors with conditional logic.
```APIDOC
## Examples
### Simple Selector
```typescript
const counterLogic = kea([
reducers({
count: [0, { /* ... */ }],
}),
selectors({
doubleCount: [(s) => [s.count], (count) => count * 2],
}),
])
// Usage
const doubleCount = counterLogic.selectors.doubleCount(state)
const value = counterLogic.values.doubleCount // inside React component
```
### Multiple Inputs
```typescript
const todoLogic = kea([
reducers({
todos: [[], { /* ... */ }],
filter: ['all', { /* ... */ }],
}),
selectors({
filteredTodos: [
(s) => [s.todos, s.filter],
(todos, filter) => {
if (filter === 'done') {
return todos.filter(t => t.done)
} else if (filter === 'pending') {
return todos.filter(t => !t.done)
}
return todos
}
],
todoCount: [(s) => [s.todos], (todos) => todos.length],
completedCount: [(s) => [s.todos], (todos) => todos.filter(t => t.done).length],
}),
])
```
### Using Props
```typescript
const itemLogic = kea([
key((props) => props.id),
props({ id: 0, multiplier: 1 } as { id: number, multiplier: number }),
reducers({
count: [0, { /* ... */ }],
}),
selectors({
countMultiplied: [
(s, p) => [s.count, p.multiplier],
(count, multiplier) => count * multiplier,
],
}),
])
```
### Connected Selectors
```typescript
const appLogic = kea([
connect({
values: [todoLogic, ['filteredTodos']],
}),
selectors({
todoMessage: [
(s) => [s.filteredTodos],
(todos) => `You have ${todos.length} todos`,
],
}),
])
```
### Custom Memoization
```typescript
const expensiveLogic = kea([
reducers({
items: [[], { /* ... */ }],
}),
selectors({
computedItems: [
(s) => [s.items],
(items) => {
// expensive computation
return items.map(item => ({
...item,
computed: heavyCalculation(item)
}))
},
{ maxSize: 1 }, // memoization options
],
}),
])
```
### Complex Computation
```typescript
const analyticsLogic = kea([
reducers({
events: [[], { /* ... */ }],
startDate: [null, { /* ... */ }],
endDate: [null, { /* ... */ }],
}),
selectors({
filteredEvents: [
(s) => [s.events, s.startDate, s.endDate],
(events, start, end) => events.filter(e => {
const date = new Date(e.timestamp)
return (!start || date >= start) && (!end || date <= end)
}),
],
eventStats: [
(s) => [s.filteredEvents],
(events) => ({
total: events.length,
byType: events.reduce((acc, e) => {
acc[e.type] = (acc[e.type] || 0) + 1
return acc
}, {}),
}),
],
}),
])
```
### Selector with Conditional Logic
```typescript
const searchLogic = kea([
reducers({
query: ['', { /* ... */ }],
results: [[], { /* ... */ }],
}),
selectors({
hasResults: [
(s) => [s.results, s.query],
(results, query) => query.length > 0 && results.length > 0,
],
displayResults: [
(s) => [s.results, s.query],
(results, query) => query.length > 0 ? results : [],
],
}),
])
```
```
--------------------------------
### Combined Kea Logic with afterMount and beforeUnmount
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/defaults-events.md
An example showcasing the integration of afterMount and beforeUnmount helpers within a Kea logic definition, alongside reducers and actions. This snippet demonstrates setting up data fetching on mount and cleanup logic on unmount.
```typescript
import { kea, reducers, actions, afterMount, beforeUnmount } from 'kea'
const newsLogic = kea([
reducers({
articles: [[], { /* ... */ }],
isLoading: [false, { /* ... */ }],
}),
actions({
setArticles: (articles: any[]) => ({ articles }),
setLoading: (loading: boolean) => ({ loading }),
}),
afterMount(() => {
newsLogic.actions.setLoading(true)
fetch('/api/articles')
.then(r => r.json())
.then(articles => newsLogic.actions.setArticles(articles))
.finally(() => newsLogic.actions.setLoading(false))
}),
beforeUnmount(() => {
// Cancel any pending requests
}),
])
```
--------------------------------
### Debug Plugin Example
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/store-plugins.md
A Kea plugin that logs messages before and after logic is built, useful for debugging.
```typescript
const debugPlugin: KeaPlugin = {
name: 'debug',
events: {
beforeLogic(logic, input) {
console.log(`Building ${logic.pathString}`)
},
afterLogic(logic, input) {
console.log(`Built ${logic.pathString}`, logic)
},
},
}
export default debugPlugin
```
--------------------------------
### propsChanged() Usage Example
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/defaults-events.md
Demonstrates how to use the propsChanged helper to react to changes in a keyed logic's props. This example loads user data when the userId prop changes.
```typescript
const userLogic = kea([
key((props) => props.userId),
props({ userId: 0 } as { userId: number }),
propsChanged((logic, oldProps) => {
if (logic.props.userId !== oldProps.userId) {
loadUser(logic.props.userId)
}
}),
])
```
--------------------------------
### Using Selectors in React Components
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/selectors.md
Demonstrates how to use selectors within a React component using `useValues` to get selector values and `useActions` to get action creators. This example shows fetching and displaying filtered todos.
```typescript
function TodoList() {
const { filteredTodos, filter } = todoLogic.useValues()
const { setFilter } = todoLogic.useActions()
return (
<>
Showing {filter} items: {filteredTodos.length}
{filteredTodos.map(todo => (
{todo.title}
))}
>
)
}
```
--------------------------------
### Listener with Connected Actions
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/listeners.md
This example shows a listener for the `setUser` action that is connected from another logic (`userLogic`). When `setUser` is dispatched in `userLogic`, this listener in `notificationLogic` is triggered, displaying a notification.
```typescript
const notificationLogic = kea([
connect({
actions: [userLogic, ['setUser']],
}),
listeners({
setUser: ({ user }, breakpoint) => {
console.log('User changed:', user.name)
showNotification(`Welcome ${user.name}`)
},
}),
])
```
--------------------------------
### Analytics Plugin Example
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/store-plugins.md
A Kea plugin that tracks logic mounting and unmounting events using an analytics service.
```typescript
const analyticsPlugin: KeaPlugin = {
name: 'analytics',
events: {
afterMount(logic) {
analytics.track('logic_mounted', {
path: logic.pathString,
})
},
afterUnmount(logic) {
analytics.track('logic_unmounted', {
path: logic.pathString,
})
},
},
}
export default analyticsPlugin
```
--------------------------------
### Wrapping a React Component with Kea Logic
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/kea.md
A concise example of wrapping a simple React component (`MyComponent`) with `counterLogic`. The logic is automatically mounted when the component renders.
```typescript
const MyComponent = () => {
const { count } = counterLogic.useValues()
return
{count}
}
// Component is wrapped and logic is auto-mounted
export default counterLogic.wrap(MyComponent)
```
--------------------------------
### useActions()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-hooks.md
Get all action creators from a logic for dispatching actions. Actions do not trigger re-renders on their own and are stable across renders.
```APIDOC
## useActions()
### Description
Get all action creators from a logic for dispatching actions. Actions do not trigger re-renders on their own and are stable across renders.
### Signature
```typescript
function useActions(
logic: BuiltLogic | LogicWrapper,
): L['actions']
```
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Parameters
- **logic** (BuiltLogic | LogicWrapper) - Required - The logic to get actions from
### Return Type
`L['actions']` - Object with all action creators.
### Request Example
```typescript
function Counter() {
const { increment, decrement } = counterLogic.useActions()
return (
)
}
```
### Response
#### Success Response (200)
- **actions** (object) - Object with all action creators.
#### Response Example
```json
{
"increment": "function",
"decrement": "function"
}
```
### Notes
- Actions don't trigger re-renders on their own
- Use with values or selectors to display state changes
- Action functions are stable across renders
```
--------------------------------
### Connect Multiple Kea Logics
Source: https://github.com/keajs/kea/blob/master/_autodocs/INDEX.md
Compose logic by connecting to other Kea logics. This example demonstrates how to access values and actions from 'otherLogic'.
```typescript
const logic = kea([
connect({
values: [otherLogic, ['value1', 'value2 as alias']],
actions: [otherLogic, ['action1']],
}),
])
```
--------------------------------
### Kea Listeners Plugin Example
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
The kea-listeners plugin allows listening for actions and running code afterwards. It provides a lightweight alternative to sagas for dispatching actions and accessing state.
```javascript
kea({
listeners: ({ actions, selectors }) => ({
[actions.updateName]: (action, { dispatch, getState }) => {
console.log(action.payload)
dispatch(actions.updateDescription('asd'))
const description = selectors.description(getState())
console.log(description)
},
})
})
```
--------------------------------
### Activate Already Installed Plugin
Source: https://github.com/keajs/kea/blob/master/_autodocs/errors.md
This error is triggered when attempting to activate the same plugin more than once. Ensure that each plugin is activated only a single time.
```typescript
const plugin = { name: 'test', events: {} }
activatePlugin(plugin)
activatePlugin(plugin) // Error!
```
```typescript
// Only activate once
activatePlugin(plugin)
```
--------------------------------
### Basic Counter Logic with React Integration
Source: https://github.com/keajs/kea/blob/master/_autodocs/REFERENCE.md
This snippet demonstrates how to create a basic counter logic using Kea, including actions, reducers, selectors, and integrating it with a React component. Use this as a starting point for simple state management needs.
```typescript
import { kea, actions, reducers, selectors } from 'kea'
const counterLogic = kea([
actions({
increment: () => null,
decrement: () => null,
}),
reducers({
count: [0, {
increment: (state) => state + 1,
decrement: (state) => state - 1,
}],
}),
selectors({
doubleCount: [(s) => [s.count], (count) => count * 2],
}),
])
function Counter() {
const { count, doubleCount } = counterLogic.useValues()
const { increment, decrement } = counterLogic.useActions()
return (
Count: {count}
Double: {doubleCount}
)
}
export default counterLogic.wrap(Counter)
```
--------------------------------
### Multiple Event Handlers for Kea Logic
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/defaults-events.md
Configure multiple lifecycle event handlers within a single `events()` call. This example demonstrates handling both `afterMount` and `beforeUnmount`.
```typescript
const listLogic = kea([
events({
afterMount: () => {
console.log('List mounted')
loadInitialData()
},
beforeUnmount: () => {
console.log('Cleaning up...')
stopPolling()
},
}),
])
```
--------------------------------
### Initialize Production Context with Plugins
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/context.md
Set up the Kea context for production by including necessary plugins and disabling debug logging. Ensure plugins are imported and passed in the plugins array.
```typescript
import { resetContext } from 'kea'
import { loaderPlugin } from 'kea-loaders'
resetContext({
plugins: [loaderPlugin],
debug: false,
})
```
--------------------------------
### Get Logic Values with useValues()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-hooks.md
Use `useValues()` to get all values from a Kea logic. Each property access triggers a selector and may cause re-renders. Unused selectors are not subscribed to.
```typescript
function Counter() {
const { count, doubleCount } = counterLogic.useValues()
return
Count: {count}, Double: {doubleCount}
}
```
--------------------------------
### keaReducer()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/store-plugins.md
Gets or creates the combined Kea reducer for a context. This function is useful for integrating Kea with React-Redux.
```APIDOC
## keaReducer()
### Description
Get or create the combined Kea reducer for a context.
### Signature
```typescript
function keaReducer(options?: Record): Reducer
```
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Parameters
- **options** (Object) - Optional - Reducer options
### Return Type
`Reducer` - Redux reducer function.
### Examples
#### Use with React-Redux
```typescript
import { keaReducer, getContext } from 'kea'
import { Provider } from 'react-redux'
const store = getContext().store
export default function App() {
return (
)
}
```
### Notes
- Combines all dynamic reducers registered with Kea
- Attached to the root reducer by the core plugin
- Handles mounting/unmounting of dynamic reducers
```
--------------------------------
### Initialize Kea with Context
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
Previously, Kea was initialized with `getStore()`. In Kea 1.0, initialize Kea with `resetContext()` and fetch the store from the context.
```javascript
resetContext({
createStore: { /* `true` or arguments for the old getStore if any */ }
})
```
```javascript
function App ({ children }) {
const { store } = getContext()
return (
{children}
)
)
```
--------------------------------
### useAllValues()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-hooks.md
Get all values from a logic, subscribing to all selectors at once. This hook causes the component to re-render if any value changes.
```APIDOC
## useAllValues()
### Description
Get all values from a logic, subscribing to all selectors at once. This hook causes the component to re-render if any value changes.
### Signature
```typescript
function useAllValues(
logic: BuiltLogic | LogicWrapper,
): L['values']
```
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Parameters
- **logic** (BuiltLogic | LogicWrapper) - Required - The logic to get values from
### Return Type
`L['values']` - Object with all logic values.
### Request Example
```typescript
function Dashboard() {
const values = todoLogic.useAllValues()
// All selectors are subscribed, component re-renders on any change
return (
{values.todos.length} todos
Filter: {values.filter}
)
}
```
### Response
#### Success Response (200)
- **values** (object) - Object with all logic values.
#### Response Example
```json
{
"todos": [],
"filter": "all"
}
```
### Difference from useValues()
- `useValues()`: Values are lazy-loaded, only used values trigger re-renders
- `useAllValues()`: All values subscribed immediately, any change causes re-render
### Notes
- Use when you need multiple values and component should update with any change
- May cause unnecessary re-renders if only some values are used
```
--------------------------------
### createStore()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/store-plugins.md
Creates a Redux store for a given context. It accepts an options object to customize store creation, including middleware, enhancers, and preloaded state.
```APIDOC
## createStore()
### Description
Create a Redux store for a context.
### Signature
```typescript
function createStore(options: Partial = {}): Store
```
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Parameters
- **options** (Partial) - Optional - Store creation options
### Return Type
`Store` - Redux store instance.
### CreateStoreOptions
```typescript
interface CreateStoreOptions {
paths: string[]
reducers: Record
preloadedState: Record | undefined
middleware: Middleware[]
compose: typeof compose
enhancers: StoreEnhancer[]
plugins: KeaPlugin[]
}
```
### Examples
#### Automatic Creation
```typescript
import { resetContext, getContext } from 'kea'
resetContext({
createStore: true, // default, creates store automatically
})
const store = getContext().store
```
#### Custom Store with Options
```typescript
import { resetContext, createStore } from 'kea'
resetContext({
createStore: false, // don't auto-create
})
const store = createStore({
middleware: [customMiddleware],
})
```
#### With Redux DevTools
```typescript
import { resetContext, createStore } from 'kea'
import { composeWithDevTools } from 'redux-devtools-extension'
resetContext({
createStore: {
compose: composeWithDevTools(),
},
})
```
#### Preloaded State
```typescript
import { createStore } from 'kea'
const store = createStore({
preloadedState: {
scenes: {
home: {
isLoading: false,
},
},
},
})
```
### Notes
- Automatically called when accessing `getContext().store` if `createStore: true`
- Called after all plugins are activated
- `plugins` option populated by `activatePlugin()`
- Returns standard Redux store
```
--------------------------------
### Callable Syntax
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/kea.md
Demonstrates the different ways a LogicWrapper can be invoked directly.
```APIDOC
## Callable Syntax
LogicWrapper can be called directly with three patterns:
```typescript
// Build without props
const builtLogic = logic()
const builtLogic = logic.build()
// Build with props
const builtLogic = logic({ id: 5 })
const builtLogic = logic.build({ id: 5 })
// Wrap React component
const WrappedComponent = logic(MyComponent)
const WrappedComponent = logic.wrap(MyComponent)
```
```
--------------------------------
### Manually Setting Store on Kea Context
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
If setting up the store manually, attach `keaReducer`s to Kea's context after store creation.
```javascript
getContext().store = store
```
--------------------------------
### Kea Actions with Reducers
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/actions.md
Demonstrates how to define actions and immediately use them within reducers to manage state changes.
```typescript
const counterLogic = kea([
actions({
increment: () => null,
decrement: () => null,
}),
reducers({
count: [0, {
increment: (state) => state + 1,
decrement: (state) => state - 1,
}],
}),
])
```
--------------------------------
### useValues()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-hooks.md
Get all values from a logic as an object. Each property access triggers a selector and may cause re-renders. Unused selectors are not subscribed to.
```APIDOC
## useValues()
### Description
Get all values from a logic as an object. Each property access triggers a selector and may cause re-renders. Unused selectors are not subscribed to.
### Signature
```typescript
function useValues(
logic: BuiltLogic | LogicWrapper,
): L['values']
```
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Parameters
- **logic** (BuiltLogic | LogicWrapper) - Required - The logic to get values from
### Return Type
`L['values']` - Object with all logic values. Each access triggers a selector.
### Request Example
```typescript
function Counter() {
const { count, doubleCount } = counterLogic.useValues()
return
Count: {count}, Double: {doubleCount}
}
```
### Response
#### Success Response (200)
- **values** (object) - Object with all logic values.
#### Response Example
```json
{
"count": 0,
"doubleCount": 0
}
```
### Notes
- Each property access on the returned object uses a selector and may trigger React re-renders
- Property access is lazy - unused selectors aren't subscribed to
- Automatically mounts/unmounts the logic in the React lifecycle
```
--------------------------------
### Connect Logic with Dynamic Keying
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
Use the `{ connect: props => ({ }) }` format to connect to logic that requires dynamic keying based on component props. This enables granular data fetching and state management.
```javascript
const faqImageLogic = kea({
connect: ({ id }) => ({
values: [
faqLogic({ id }), ['isVisible']
]
}),
// other logic for the image...
})
function RawFaqImage ({ id, title, isVisible }) {
if (!isVisible) {
return null
}
return
}
const FaqImage = faqImageLogic(RawFaqImage)
function AllFaqs () {
const faqs = [ /* { id, title, body }, ... */ ]
return (
{faqs.map(faq => (
<>
>
))}
)
}
```
--------------------------------
### Kea Router Plugin Example
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
The kea-router plugin bridges Kea with react-redux and connected-react-router. It maps actions to URLs and URLs back to actions.
```javascript
kea({
actionToUrl: ({ actions }) => ({
[actions.selectEmail]: () => `/signup?type=email`,
[actions.unselectEmail]: () => `/signup`,
[actions.openLesson]: ({ id }, action) => `/open/${id}`
}),
urlToAction: ({ actions }) => ({
'/signup?type=email': url => actions.selectEmail(),
'/signup': url => actions.unselectEmail(),
'/open/': (url) => actions.openLesson(parseInt(url.split('/')[2]))
}),
})
```
--------------------------------
### Configuring Kea Context with Plugins
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
Shows how to reset and configure the Kea context, including adding plugins like sagaPlugin and localStoragePlugin. This is typically done at the top of the application and is crucial for server-side rendering.
```javascript
resetContext({
plugins: [sagaPlugin, localStoragePlugin],
// other options like defaults, plugin config, redux strategy, debug mode, etc
})
```
--------------------------------
### afterMount()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/defaults-events.md
A shorthand for `events({ afterMount: ... })`. This function allows you to execute code after a logic component has been mounted and is ready. It's useful for initializing data or performing actions that depend on the logic being fully set up.
```APIDOC
## afterMount()
### Description
Shorthand for `events({ afterMount: ... })`. Executes code after a logic component has been mounted and is ready.
### Method Signature
```typescript
function afterMount(
input: (logic: L) => void,
): LogicBuilder
```
### Usage Example
```typescript
const dataLogic = kea([
afterMount((logic) => {
console.log('Loading data for', logic.path)
fetch('/api/data').then(r => r.json()).then(console.log)
}),
])
```
```
--------------------------------
### Define Selectors with Kea
Source: https://github.com/keajs/kea/blob/master/_autodocs/INDEX.md
Use selectors to derive computed values from state. This example shows how to define a selector that doubles the 'count' value.
```typescript
const logic = kea([
reducers({ count: [0, {}] }),
selectors({
doubled: [(s) => [s.count], (c) => c * 2],
}),
])
```
--------------------------------
### Mount Logic with BindLogic or wrap()
Source: https://github.com/keajs/kea/blob/master/_autodocs/configuration.md
Mount logic using the BindLogic component or the logic.wrap() utility. These methods ensure the logic is properly mounted within the component tree.
```typescript
// Option 3: Use BindLogic or logic.wrap()
```
--------------------------------
### Basic Kea Logic Definition
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/kea.md
Defines a simple counter logic with actions, reducers, and selectors. This is a fundamental example of how to structure Kea logic.
```typescript
import { kea, actions, reducers, selectors } from 'kea'
const counterLogic = kea([
actions({
increment: () => null,
decrement: () => null,
}),
reducers({
count: [0, {
increment: (state) => state + 1,
decrement: (state) => state - 1,
}],
}),
selectors({
doubleCount: [(s) => [s.count], (count) => count * 2],
}),
])
```
--------------------------------
### useMountedLogic()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-hooks.md
Mount a logic and get the built logic instance. This hook ensures the logic is mounted within the React component's lifecycle.
```APIDOC
## useMountedLogic()
### Description
Mount a logic and get the built logic instance. This hook ensures the logic is mounted within the React component's lifecycle.
### Signature
```typescript
function useMountedLogic(
logic: BuiltLogic | LogicWrapper,
): BuiltLogic
```
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Parameters
- **logic** (BuiltLogic | LogicWrapper) - Required - The logic to mount
### Return Type
`BuiltLogic` - The mounted logic instance.
### Request Example
```typescript
function ItemDetail({ itemId }: { itemId: number }) {
const logic = useMountedLogic(itemLogic({ id: itemId }))
// Component has full access to the logic instance
return
{logic.values.name}
}
```
### Response
#### Success Response (200)
- **logicInstance** (BuiltLogic) - The mounted logic instance.
#### Response Example
```json
{
"logicInstance": "object"
}
```
```
--------------------------------
### useAsyncActions()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-hooks.md
Get async versions of action creators that return Promises. Useful for waiting for side effects like API calls to complete.
```APIDOC
## useAsyncActions()
### Description
Get async versions of action creators that return Promises. Useful for waiting for side effects like API calls to complete.
### Signature
```typescript
function useAsyncActions(
logic: BuiltLogic | LogicWrapper,
): L['asyncActions']
```
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Parameters
- **logic** (BuiltLogic | LogicWrapper) - Required - The logic to get async actions from
### Return Type
`L['asyncActions']` - Object with async action creators returning Promises.
### Request Example
```typescript
function UserProfile() {
const { fetchUser } = userLogic.useAsyncActions()
const { user } = userLogic.useValues()
const handleLoad = async () => {
try {
await fetchUser(5)
console.log('User loaded')
} catch (error) {
console.error('Failed to load user')
}
}
return (
{user &&
{user.name}
}
)
}
```
### Response
#### Success Response (200)
- **asyncActions** (object) - Object with async action creators returning Promises.
#### Response Example
```json
{
"fetchUser": "function"
}
```
### Notes
- Async actions return Promises that resolve when all listeners complete
- Useful for waiting for side effects to complete (e.g., API calls)
- Requires listeners to be defined for the actions to be async
```
--------------------------------
### Dynamic Logics with Key and Props
Source: https://github.com/keajs/kea/blob/master/_autodocs/REFERENCE.md
This snippet shows how to create dynamic logic instances based on props, using `key` and `props`. This pattern is useful when you need separate logic states for different items, identified by an ID or other properties.
```typescript
const itemLogic = kea([
key((props) => props.id),
props({ id: 0 } as { id: number }),
reducers({
name: ['', { /* ... */ }],
}),
])
// Create separate instances per id
const item1 = itemLogic({ id: 1 })
const item2 = itemLogic({ id: 2 })
```
--------------------------------
### Reducer Definition Formats
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/reducers.md
Illustrates different formats for defining reducers, including initial value, options, and action handlers.
```typescript
// Format 1: [initialValue, actionHandlers]
count: [0, {
increment: (state) => state + 1,
decrement: (state) => state - 1,
}]
```
```typescript
// Format 2: [initialValue, options, actionHandlers]
count: [0, { some: 'option' }, {
increment: (state) => state + 1,
}]
```
```typescript
// Format 3: Just action handlers (initial value = null)
status: {
setStatus: (_, { status }) => status,
}
```
```typescript
// Format 4: Function returning initial value
count: [
(state, props) => props.initialCount ?? 0,
{
increment: (state) => state + 1,
}
]
```
--------------------------------
### Single Event Handler for Kea Logic
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/defaults-events.md
Define a single lifecycle event handler using `events()`. This example shows how to log a message when the logic mounts.
```typescript
const dataLogic = kea([
events({
afterMount: () => {
console.log('Data logic mounted')
},
}),
])
```
--------------------------------
### Mount Keyed Kea Logic Without React
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
For keyed logic, first build the logic instance with specific keys, then mount it. This is necessary when logic depends on dynamic identifiers.
```javascript
const { store } = getContext()
const logic = kea({ key: ({ id }) => id, /* some actions and reducers */})
const builtLogic = logic({ id: 12 })
const unmount = builtLogic.mount()
store.dispatch(builtLogic.actions.someAction('value'))
const state = builtLogic.selectors.getValue(store.getState())
unmount()
```
--------------------------------
### Kea Context Options
Source: https://github.com/keajs/kea/blob/master/_autodocs/configuration.md
Configure Kea context options during application startup using resetContext or openContext.
```typescript
resetContext({
plugins: [plugin1, plugin2],
createStore: true,
defaults: {},
debug: false,
proxyFields: true,
flatDefaults: false,
attachStrategy: 'dispatch',
detachStrategy: 'dispatch',
defaultPath: ['kea', 'logic'],
disableAsyncActions: false,
})
```
--------------------------------
### Kea Immer Plugin Example
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
The kea-immer plugin enables mutable state updates in reducers by specifying `{ immer: true }`. This allows direct modification of state objects.
```javascript
@kea({
actions: () => ({
increment: (amount = 1) => ({ amount }),
decrement: (amount = 1) => ({ amount })
}),
reducers: ({ actions, key, props }) => ({
counter: [{ count: 0 }, PropTypes.object, { immer: true }, {
[actions.increment]: (state, payload) => {
state.count += payload.amount
},
[actions.decrement]: (state, payload) => {
state.count -= payload.amount
}
}]
})
})
```
--------------------------------
### Mount Logic Before Use
Source: https://github.com/keajs/kea/blob/master/_autodocs/errors.md
To prevent production app crashes with 'not mounted', ensure all logics are mounted before they are accessed. This can be done manually, via hooks, or `BindLogic`.
```typescript
// Always mount before accessing
const built = logic.build()
built.mount()
// Or use hooks in React
function Component() {
const { values } = logic.useValues()
}
// Or use BindLogic
```
--------------------------------
### Dispatch Actions with useActions()
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/react-hooks.md
Use `useActions()` to get all action creators from a Kea logic for dispatching actions. Action functions are stable across renders and do not trigger re-renders on their own.
```typescript
function Counter() {
const { increment, decrement } = counterLogic.useActions()
return (
)
}
```
--------------------------------
### Create Dynamic Kea Logics with Key and Props
Source: https://github.com/keajs/kea/blob/master/_autodocs/INDEX.md
Define dynamic logic instances using 'key' and 'props'. This allows for multiple instances of the same logic, each identified by unique properties.
```typescript
const logic = kea([
key((props) => props.id),
props({ id: 0 } as { id: number }),
// ...
])
const instance = logic({ id: 5 })
```
--------------------------------
### Constants Access in Kea Logic
Source: https://github.com/keajs/kea/blob/master/docs/CHANGES-1.0.md
Direct access to constants on unbuilt keyed logic as a property is no longer supported. Constants can still be used within the logic, for example, in reducers.
```javascript
const logic = kea({
constants: () => ['SOMETHING', 'BLABLA']
})
logic.constants == { SOMETHING: 'SOMETHING', BLABLA: 'BLABLA' }
```
```javascript
const logic = kea({
key: props => props.id,
constants: () => ['SOMETHING', 'BLABLA']
})
logic.constants == undefined
```
```javascript
const logic = kea({
key: props => props.id,
constants: () => ['SOMETHING', 'BLABLA'],
reducers: ({ constants }) => ({
bla: [contants.SOMETHING, { ... }]
})
})
```
--------------------------------
### Mounting Kea Logic Outside React
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/kea.md
Demonstrates mounting a logic instance directly using `build()` and `mount()`, bypassing React. It shows how to access values and unmount the logic.
```typescript
const builtLogic = logic.build()
const unmount = builtLogic.mount()
// Use the logic...
console.log(builtLogic.values.count)
// Clean up
unmount()
```
--------------------------------
### ContextOptions
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/context.md
Defines the configuration options available when creating or resetting the Kea context. These options control various aspects of Kea's behavior, including plugin activation, store creation, and default reducer values.
```APIDOC
## ContextOptions
### Description
Options for context creation. These options are set at context creation time and affect how logics are built and reducers are attached. Plugin-specific options are handled by the respective plugins.
### Interface Definition
```typescript
interface ContextOptions extends Partial {
plugins?: KeaPlugin[]
createStore?: boolean | Partial
defaults?: Record
}
interface InternalContextOptions {
debug: boolean
proxyFields: boolean
flatDefaults: boolean
attachStrategy: 'dispatch' | 'replace'
detachStrategy: 'dispatch' | 'replace' | 'persist'
defaultPath: string[]
disableAsyncActions: boolean
}
```
### Parameters
#### Path Parameters
- **plugins** (KeaPlugin[]) - Optional - Plugins to activate. Defaults to `[]`.
- **createStore** (boolean | object) - Optional - Whether to create Redux store, or store options. Defaults to `true`.
- **defaults** (Object) - Optional - Default reducer values. Defaults to `{}`.
- **debug** (boolean) - Optional - Enable debug logging. Defaults to `false`.
- **proxyFields** (boolean) - Optional - Allow accessing logic fields directly. Defaults to `true`.
- **flatDefaults** (boolean) - Optional - Use flat default structure. Defaults to `false`.
- **attachStrategy** (string) - Optional - How to attach dynamic reducers. Defaults to `'dispatch'`.
- **detachStrategy** (string) - Optional - How to detach dynamic reducers. Defaults to `'dispatch'`.
- **defaultPath** (string[]) - Optional - Default path for logics. Defaults to `['kea', 'logic']`.
- **disableAsyncActions** (boolean) - Optional - Disable async action tracking. Defaults to `false`.
### Examples
#### Development Context
```typescript
import { resetContext } from 'kea'
resetContext({
debug: true,
defaults: {
scenes: {
home: {
isLoading: false,
},
},
},
})
```
#### Production Context with Plugins
```typescript
import { resetContext } from 'kea'
import { loaderPlugin } from 'kea-loaders'
resetContext({
plugins: [loaderPlugin],
debug: false,
})
```
#### Custom Store Creation
```typescript
import { resetContext } from 'kea'
import { composeWithDevTools } from 'redux-devtools-extension'
resetContext({
createStore: {
compose: composeWithDevTools(),
},
})
```
### Notes
- Options set at context creation time.
- Most options affect how logics are built and reducers attached.
- Plugin-specific options handled by plugins.
- Call `resetContext()` during app initialization.
```
--------------------------------
### Listener with Previous State Access
Source: https://github.com/keajs/kea/blob/master/_autodocs/api-reference/listeners.md
An example of a listener for the `submit` action that accesses the `previousState` and `currentState` to detect changes. This is useful for auditing or conditional logic based on state transitions.
```typescript
const formLogic = kea([
actions({
submit: () => null,
}),
listeners({
submit: ({ payload }, breakpoint, action, previousState) => {
const changes = detectChanges(previousState, currentState)
if (changes.length > 0) {
console.log('Form changed:', changes)
}
},
}),
])
```
--------------------------------
### Kea Core Import
Source: https://github.com/keajs/kea/blob/master/_autodocs/INDEX.md
Import the main 'kea' function to define your logic.
```typescript
// Main
import { kea } from 'kea'
```