TL;DR
New tag: <BindLogic logic={itemLogic} props={{ id: 12 }}>
.
It lets you write useValues(itemLogic)
instead
of useValues(itemLogic({ id: 12 }))
in nested children. Powered by React Context.
When using keyed logics it's easy to get into a situation where you need to pass props similar to this:
import { kea, useValues } from 'kea'
const itemLogic = kea({ key: (props) => props.id /* ... */ })
function List() {
return (
<>
<Item id={12} />
<Item id={15} />
</>
)
}
function Item({ id }) {
const { className } = useValues(itemLogic({ id }))
return (
<div className={className}>
<Title id={id} />
<Body id={id} />
</div>
)
}
function Title({ id }) {
const { title, url } = useValues(itemLogic({ id }))
return <a href={url}>{title}</a>
}
function Body({ id }) {
const { body } = useValues(itemLogic({ id }))
return <div>{body}</div>
}
In Kea 2.3 you can use <BindLogic>
to clear this up:
import { kea, useValues, BindLogic } from 'kea'
const itemLogic = kea({ key: (props) => props.id /* ... */ })
function List() {
return (
<>
<BindLogic logic={itemLogic} props={{ id: 12 }}>
<Item />
</BindLogic>
<BindLogic logic={itemLogic} props={{ id: 15 }}>
<Item />
</BindLogic>
</>
)
}
function Item() {
const { className } = useValues(itemLogic)
return (
<div className={className}>
<Title />
<Body />
</div>
)
}
function Title() {
const { title, url } = useValues(itemLogic)
return <a href={url}>{title}</a>
}
function Body() {
const { body } = useValues(itemLogic)
return <div>{body}</div>
}
When you write <BindLogic logic={itemLogic} props={{ id: 12 }}>
, Kea stores a specific build of
itemLogic
inside a React Context. Any nested children will get that when calling e.g: useValues(itemLogic)
.