Skip to content

Instantly share code, notes, and snippets.

@stramel
Created March 31, 2020 21:54
Show Gist options
  • Save stramel/0a4d169a1677e891903f76d344609e08 to your computer and use it in GitHub Desktop.
Save stramel/0a4d169a1677e891903f76d344609e08 to your computer and use it in GitHub Desktop.
Field Array store and hook factory
import { createContext, createElement, useContext, useEffect, useMemo, useState, ReactNode } from 'react'
import { useFormContext } from 'react-hook-form'
function createFieldArray<T>(name: string) {
const storeContext = createContext()
function StoreProvider({children, defaultValue}: {children: ReactNode, defaultValue: T[]}) {
const { register, setValue, unregister } = useFormContext()
const [items, setItems] = useState<T[]>(defaultValue)
// Manually register our array field
useEffect(() => {
register({ name })
return () => {
unregister(name)
}
}, [])
// Update the form value on change
useEffect(() => {
setValue(name, items)
}, [items, name, setValue])
const value = useMemo(() => (
{
items,
insert(item: T, index: number) {
setItems(items => {
const tempItems = [...items]
tempItems.splice(index, 0, item)
return tempItems
})
},
remove(index: number) {
setItems(items => {
const tempItems = [...items]
tempItems.splice(index, 1)
return tempItems
})
},
append(item: T) {
setItems(items => [...items, item])
},
prepend(item: T) {
setItems(items => [item, ...items])
},
}
), [items, setItems])
return createElement(storeContext.Provider, { value }, children)
}
function useStore() {
return useContext(storeContext)
}
return [StoreProvider, useStore]
}
const [TodosField, useTodosField] = createFieldArray('todos')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment