[Recoil] Intermediate Selectors
interface:
export type ElementStyle = {
position: {top: number; left: number}
size: {width: number; height: number}
}
export type Element = {style: ElementStyle; image?: {id: number; src: string}}
Let's say we have this selector:
const imageInfoState = selector({
key: 'imageInfoState',
get: ({get}) => {
const id = get(selectElementAtom)
if (id === null) return
const element = get(elementAtom(id))
const imageId = element.image?.id
if (imageId === undefined) return
return callApi('image-details', {queryParams: {seed: imageId}})
},
})
So everytime when Element
changes, for example when we drag the image, position
will changed, the callApi
will be triggered.
It will cause the component being re-renderred too many times.
How to solve the problem?
const element = get(elementAtom(id))
This code will be update everytime when Element position changes.
But we don't want trigger callApi
if imageId
doesn't change.
We can use intermediate selector:
const imageIdState = selector({
key: 'imageId',
get: ({get}) => {
const id = get(selectElementAtom)
if (id === null) return
const element = get(elementAtom(id))
return element.image?.id
},
})
const imageInfoState = selector({
key: 'imageInfoState',
get: ({get}) => {
const imageId = get(imageIdState) // use intermediate selector
if (imageId === undefined) return
return callApi('image-details', {queryParams: {seed: imageId}})
},
})