Created
December 25, 2021 19:56
-
-
Save x1unix/d5b3c6638a567b2befe3ff28ee1b32cb to your computer and use it in GitHub Desktop.
React - Partial state update
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
/** | |
* Performs partial object update | |
* @param obj | |
* @param value | |
* @param path | |
*/ | |
export function partialUpdateObject<T=any>(obj: T, value: any, path: string[]): T { | |
const key = path.pop(); | |
if (!key) { | |
return obj; | |
} | |
if (!path.length) { | |
return obj ? {...obj, [key]: value} : {[key]: value} as T; | |
} | |
const nestedObj = obj[key]; | |
const updatedNestedValue = partialUpdateObject<typeof nestedObj>(nestedObj, value, path); | |
return { ...obj, [key]: updatedNestedValue}; | |
} | |
/** | |
* Partially updates nested state. | |
* | |
* @param setter State setter function from `useState` | |
* @param path Object update path | |
* @param value New value | |
*/ | |
export function partialSetState<T>(setter: React.Dispatch<React.SetStateAction<T>>, path: string, value: any) { | |
const chunks = path.split('.').reverse(); | |
if (chunks.length === 1) { | |
setter(prev => ({ | |
...prev, [path]: value, | |
})); | |
return; | |
} | |
setter(prevState => ( | |
partialUpdateObject<T>(prevState, value, chunks) | |
)); | |
} | |
/** | |
* Wraps passed React state dispatcher with partial state setter. | |
* | |
* Allows doing partial nested state update for complex objects. | |
* | |
* @see partialSetState | |
* @example | |
* ``` | |
* const [ value, setValue ] = useState({foo: {bar: 2}}); | |
* const updateValue = usePartialDispatch(setValue); | |
* | |
* updateValue('foo.bar', 3); | |
* ``` | |
* @param dispatch | |
*/ | |
export function usePartialDispatch<T>(dispatch: React.Dispatch<React.SetStateAction<T | undefined>>) { | |
return (path: string, value: any) => partialSetState<T | undefined>(dispatch, path, value); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment