Skip to content

Instantly share code, notes, and snippets.

@geocine
Created December 24, 2019 13:00
Show Gist options
  • Save geocine/64b6219a4b6dc0eff5e8332c038d8005 to your computer and use it in GitHub Desktop.
Save geocine/64b6219a4b6dc0eff5e8332c038d8005 to your computer and use it in GitHub Desktop.
useFieldArray (immer)
import { useCallback, useRef } from 'react';
import { useField, useFormikContext } from 'formik';
import produce from 'immer';
export const useFieldArray = (props) => {
const [field, meta] = useField(props);
const fieldArray = useRef(field.value);
const { setFieldValue } = useFormikContext();
const push = useCallback(
(value) => {
fieldArray.current = produce(fieldArray.current, (draft) => {
draft.push(value);
});
setFieldValue(field.name, fieldArray.current);
},
[field.name, setFieldValue]
);
const swap = useCallback(
(indexA, indexB) => {
const swapA = fieldArray.current[indexA];
const swapB = fieldArray.current[indexB];
fieldArray.current = produce(fieldArray.current, (draft) => {
draft.splice(indexA, 1, swapB);
draft.splice(indexB, 1, swapA);
});
setFieldValue(field.name, fieldArray.current);
},
[field.name, setFieldValue]
);
const move = useCallback(
(from, to) => {
const toMove = fieldArray.current[from];
fieldArray.current = produce(fieldArray.current, (draft) => {
draft.splice(from, 1);
draft.splice(to, 0, toMove);
});
setFieldValue(field.name, fieldArray.current);
},
[field.name, setFieldValue]
);
const insert = useCallback(
(index, value) => {
fieldArray.current = produce(fieldArray.current, (draft) => {
draft.splice(index, 0, value);
});
setFieldValue(field.name, fieldArray.current);
},
[field.name, setFieldValue]
);
const unshift = useCallback(
(value) => {
fieldArray.current = produce(fieldArray.current, (draft) => {
draft.unshift(value);
});
setFieldValue(field.name, fieldArray.current);
return fieldArray.current.length;
},
[field.name, setFieldValue]
);
const remove = useCallback(
(index) => {
const removedItem = fieldArray.current[index];
fieldArray.current = produce(fieldArray.current, (draft) => {
draft.splice(index, 1);
});
setFieldValue(field.name, fieldArray.current);
return removedItem;
},
[field.name, setFieldValue]
);
const pop = useCallback(() => {
const lastIndex = fieldArray.current.length - 1;
const poppedItem = fieldArray.current[lastIndex];
fieldArray.current = produce(fieldArray.current, (draft) => {
draft.splice(lastIndex, 1);
});
setFieldValue(field.name, fieldArray.current);
return poppedItem;
}, [field.name, setFieldValue]);
const replace = useCallback(
(index, value) => {
fieldArray.current = produce(fieldArray.current, (draft) => {
draft.splice(index, 1, value);
});
setFieldValue(field.name, fieldArray.current);
},
[field.name, setFieldValue]
);
return [
field,
meta,
{
push,
swap,
move,
insert,
unshift,
remove,
pop,
replace
}
];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment