首页 > 其他分享 >[Recoil] Overview

[Recoil] Overview

时间:2022-10-12 01:33:26浏览次数:46  
标签:set return get Overview element Recoil const id

AtomFamily

For example, you have list of elements. We want to avoid that single elemenet got changed, whole list got re-render. Also want to share the single element state to other component. We can use atom (for list) and atomFmaily (for each element)

[PS] Using Redux with selector can also achieve this

for the list itself, you can use atom to model it.

for each elements in the list, can use atomFamily, it is a high order function which accept a param, for list of elements, the params would be the id of each element.

It is easy to get each element by using useRecoilState(elementAtom(id)), and those state are shareable with other component.

// list
export const elementsAtom = atom<number[]>({
    key: 'elementsState',
    default: [],
})

// each element
export const elementAtom = atomFamily<Element, number>({
    key: 'elementState',
    default: {
        style: {
            position: {top: 50, left: 50},
            size: {width: 50, height: 50},
        },
    },
})

const [element, setElement] = useRecoilState(elementAtom(id))

SelectorFamily

Benefits of Selectors:

  • Get and Set logic combined
  • Same API as Atoms
  • Shareable, self-containaed state
  • Async data fetching
    • Has caching built-in for the same params
    • Handle race condition for you when data fetching

Reaons to use SelectorFamily:

  • Similar concept as factory
  • The params should be serialisable
    • Recoil compare the param by value not by reference
    • selectorFamily({userId: 1}) === selectorFamily({userId: 1})
    • Only fetch data once
    • In Menu & Post both call userState, but data fetch only once
export const editPropertiesState = selectorFamily<number, {path: string; id: number}>({
    key: 'editPropertiesState',
    get:
        ({path, id}) =>
        ({get}) => {
            const element = get(elementAtom(id))
            return lodash_get(element, path)
        },
    set:
        ({path, id}) =>
        ({get, set}, newValue) => {
            const element = get(elementAtom(id))
            const newElement = produce(element, (draft) => {
                lodash_set(draft, path, newValue)
            })
            set(elementAtom(id), newElement)
        },
})

How to refetch data by using selector/selectorFamily

Example

const weatherState = selectorFamily({
    key: 'weather',
    get:
        (userId: number) =>
        async ({get}) => {
            get(weatherRequestIdState(userId))
            const user = get(userState(userId))
            const weather = await getWeather(user.address.city)
            return weather
        },
})

// #region refetch
/* Refetch request by using selector */
// 1. create a request Id atom
const weatherRequestIdState = atomFamily({
    key: 'weatherRequestId',
    default: 0,
})
// 2. create a custom hook to increase the request id
const useRefetchWeather = (userId: number) => {
    const setRequestId = useSetRecoilState(weatherRequestIdState(userId))
    return () => setRequestId((id) => id + 1)
}
// 3. call get(weatherRequestIdState(userId)) in selectFamily where requrest need to be refetch
// 4. Use useRefetchWeather(userId) hook
// #endregion

export const UserWeather = ({userId}: {userId: number}) => {
    const weather = useRecoilValue(weatherState(userId))
    const userData = useRecoilValue(userState(userId))
    const refetch = useRefetchWeather(userId)
    return (
        <>
            <Text>
                <b>Weather for {userData.address.city}: </b> {weather} C
            </Text>
            <Text onClick={refetch}>(Refresh weather)</Text>
        </>
    )
}

UseRecoilCallback

In a case that when we add a new item into list, by the same time, we want to upate the newly added item.

In this project, we have element list, when we add a new image rectangle, we want to push a new rectangle into the list, then update that new rectangle to set image prop.

The problem is by the time we add new rectangle intot the list, we don't have rectangle instance yet. Therefore we cannot set image prop.

useRecoilCallback(({set, get}) => (param) => {...})

    const elements = useRecoilValue(elementsAtom)
    const newId = elements.length
    const insertElement = useRecoilCallback(({set}) => (type: 'rectangle' | 'image') => {
        // add a new rectangle into the list
        set(elementsAtom, (elements) => [...elements, elements.length])

        if (type === 'image') {
            // newId will be the newly added rectangle
            set(elementAtom(newId), {
                style: defaultStyle,
                image: getRandomImage(),
            })
        }
    })

[PS] found this solution also works

    const [elements, setElements] = useRecoilState(elementsAtom)
    const newId = elements.length
    const [_, setNewElement] = useRecoilState(elementAtom(newId))
    function setNewItem(type: 'rectangle' | 'image') {
        setElements((els) => [...els, els.length])
        if (type === 'image') {
            // newId will be the newly added rectangle
            setNewElement((el) => ({
                ...el,
                style: defaultStyle,
                image: getRandomImage(),
            }))
        }
    }

Intermediate Selectors

What is the problem for the following code?

const imageInfoState = selector({
    key: 'imageInfoState',
    get: ({get}) => {
        const id = get(selectElementAtom)
        if (id === null) return

        const element = get(elementAtom(id))
        return element.image?.id
        if (imageId === undefined) return

        return callApi('image-details', {queryParams: {seed: imageId}})
    },
})

标签:set,return,get,Overview,element,Recoil,const,id
From: https://www.cnblogs.com/Answer1215/p/16783161.html

相关文章

  • [Recoil] Optimising API Calls
    UsingcacheclasstoreduceAPIcallsimport{Button}from'@chakra-ui/button'import{Input}from'@chakra-ui/input'import{Box,Divider,Heading,VStack}fr......
  • [Recoil] Intermediate Selectors
     interface:exporttypeElementStyle={position:{top:number;left:number}size:{width:number;height:number}}exporttypeElement={style:......
  • 论文笔记:An Overview of Query Optimization in Relational Systems
    论文笔记:AnOverviewofQueryOptimizationinRelationalSystems这篇文章发表于1998年,是数据库系统查询优化领域的入门必读文章。执行计划物理算子构成的树状结构......
  • Overview of Database Link数据库链接概述
    什么是数据库链接?数据库链接是一个指针,它定义了从Oracle数据库服务器到另一个数据库服务器的单向通信路径。对于公共和私有数据库链接,链接指针实际上被定义为数据字典......