From cd6793f6418a9533290252bc83c3dc1a98f3ac3f Mon Sep 17 00:00:00 2001 From: James Date: Thu, 2 Jul 2020 12:48:58 -0400 Subject: [PATCH] WIP fixes to form state optimizations --- demo/collections/FlexibleContent.js | 3 + src/client/components/forms/Form/index.js | 83 +++++++++---------- .../forms/field-types/Flexible/index.js | 8 +- .../forms/field-types/Repeater/index.js | 4 +- .../forms/field-types/rowReducer.js | 9 +- 5 files changed, 53 insertions(+), 54 deletions(-) diff --git a/demo/collections/FlexibleContent.js b/demo/collections/FlexibleContent.js index ec1c764554..878c3dea69 100644 --- a/demo/collections/FlexibleContent.js +++ b/demo/collections/FlexibleContent.js @@ -9,6 +9,9 @@ module.exports = { singular: 'Flexible Content', plural: 'Flexible Content', }, + policies: { + read: () => true, + }, fields: [ { name: 'layout', diff --git a/src/client/components/forms/Form/index.js b/src/client/components/forms/Form/index.js index 642d860138..bc2ed67c1c 100644 --- a/src/client/components/forms/Form/index.js +++ b/src/client/components/forms/Form/index.js @@ -57,22 +57,21 @@ const Form = (props) => { const { refreshToken } = useUser(); const contextRef = useRef({ ...initContextState }); - const { current: contextValue } = contextRef; const [fields, dispatchFields] = useReducer(fieldReducer, {}); - contextValue.fields = fields; - contextValue.dispatchFields = dispatchFields; + contextRef.current.fields = { ...fields }; + contextRef.current.dispatchFields = dispatchFields; - contextValue.submit = (e) => { + contextRef.current.submit = (e) => { if (disabled) { e.preventDefault(); return false; } e.stopPropagation(); - contextValue.setSubmitted(true); + contextRef.current.setSubmitted(true); - const isValid = contextValue.validateForm(); + const isValid = contextRef.current.validateForm(); // If not valid, prevent submission if (!isValid) { @@ -106,18 +105,18 @@ const Form = (props) => { behavior: 'smooth', }); - const formData = contextValue.createFormData(); - contextValue.setProcessing(true); + const formData = contextRef.current.createFormData(); + contextRef.current.setProcessing(true); // Make the API call from the action return requests[method.toLowerCase()](action, { body: formData, }).then((res) => { - contextValue.setModified(false); + contextRef.current.setModified(false); if (typeof handleAjaxResponse === 'function') return handleAjaxResponse(res); return res.json().then((json) => { - contextValue.setProcessing(false); + contextRef.current.setProcessing(false); clearStatus(); if (res.status < 400) { @@ -154,7 +153,7 @@ const Form = (props) => { valid: false, errorMessage: err.message, path: err.field, - value: fields?.[err.field]?.value, + value: contextRef.current.fields?.[err.field]?.value, }); }); @@ -194,30 +193,30 @@ const Form = (props) => { return true; }; - contextValue.getFields = () => { - return fields; + contextRef.current.getFields = () => { + return contextRef.current.fields; }; - contextValue.getField = (path) => { - return fields[path]; + contextRef.current.getField = (path) => { + return contextRef.current.fields[path]; }; - contextValue.getData = () => { - return reduceFieldsToValues(fields, true); + contextRef.current.getData = () => { + return reduceFieldsToValues(contextRef.current.fields, true); }; - contextValue.getSiblingData = (path) => { - let siblingFields = fields; + contextRef.current.getSiblingData = (path) => { + let siblingFields = contextRef.current.fields; // If this field is nested // We can provide a list of sibling fields if (path.indexOf('.') > 0) { const parentFieldPath = path.substring(0, path.lastIndexOf('.') + 1); - siblingFields = Object.keys(fields).reduce((siblings, fieldKey) => { + siblingFields = Object.keys(contextRef.current.fields).reduce((siblings, fieldKey) => { if (fieldKey.indexOf(parentFieldPath) === 0) { return { ...siblings, - [fieldKey.replace(parentFieldPath, '')]: fields[fieldKey], + [fieldKey.replace(parentFieldPath, '')]: contextRef.current.fields[fieldKey], }; } @@ -228,15 +227,15 @@ const Form = (props) => { return reduceFieldsToValues(siblingFields, true); }; - contextValue.getDataByPath = (path) => { + contextRef.current.getDataByPath = (path) => { const pathPrefixToRemove = path.substring(0, path.lastIndexOf('.') + 1); const name = path.split('.').pop(); - const data = Object.keys(fields).reduce((matchedData, key) => { + const data = Object.keys(contextRef.current.fields).reduce((matchedData, key) => { if (key.indexOf(`${path}.`) === 0) { return { ...matchedData, - [key.replace(pathPrefixToRemove, '')]: fields[key], + [key.replace(pathPrefixToRemove, '')]: contextRef.current.fields[key], }; } @@ -248,12 +247,12 @@ const Form = (props) => { return unflattenedData?.[name]; }; - contextValue.getUnflattenedValues = () => { - return reduceFieldsToValues(fields); + contextRef.current.getUnflattenedValues = () => { + return reduceFieldsToValues(contextRef.current.fields); }; - contextValue.validateForm = () => { - return !Object.values(fields).some((field) => { + contextRef.current.validateForm = () => { + return !Object.values(contextRef.current.fields).some((field) => { if (field.valid === false) { console.log(field, ' is not valid'); } @@ -261,21 +260,21 @@ const Form = (props) => { }); }; - contextValue.createFormData = () => { - const data = reduceFieldsToValues(fields); + contextRef.current.createFormData = () => { + const data = reduceFieldsToValues(contextRef.current.fields); return objectToFormData(data, { indices: true }); }; - contextValue.setModified = (modified) => { - contextValue.modified = modified; + contextRef.current.setModified = (modified) => { + contextRef.current.modified = modified; }; - contextValue.setSubmitted = (submitted) => { - contextValue.submitted = submitted; + contextRef.current.setSubmitted = (submitted) => { + contextRef.current.submitted = submitted; }; - contextValue.setProcessing = (processing) => { - contextValue.processing = processing; + contextRef.current.setProcessing = (processing) => { + contextRef.current.processing = processing; }; useThrottledEffect(() => { @@ -283,28 +282,26 @@ const Form = (props) => { }, 15000, [fields]); useEffect(() => { - contextValue.modified = false; - }, [locale, contextValue.modified]); + contextRef.current.modified = false; + }, [locale, contextRef.current.modified]); const classes = [ className, baseClass, ].filter(Boolean).join(' '); - const { submit } = contextValue; - return (
- + { const dataToInitialize = initialData || defaultValue; const [rows, dispatchRows] = useReducer(reducer, []); const { customComponentsPath } = useRenderedFields(); - const { getDataByPath } = useFormFields(); + const { getDataByPath } = useForm(); const addRow = (index, blockType) => { const data = getDataByPath(path); @@ -179,10 +179,6 @@ const Flexible = (props) => { name: 'blockType', type: 'text', hidden: 'admin', - }, { - name: 'blockName', - type: 'text', - hidden: 'admin', }, ]} /> diff --git a/src/client/components/forms/field-types/Repeater/index.js b/src/client/components/forms/field-types/Repeater/index.js index 29ccb69d69..f4464950f6 100644 --- a/src/client/components/forms/field-types/Repeater/index.js +++ b/src/client/components/forms/field-types/Repeater/index.js @@ -8,7 +8,7 @@ import Button from '../../../elements/Button'; import DraggableSection from '../../DraggableSection'; import reducer from '../rowReducer'; import { useRenderedFields } from '../../RenderFields'; -import useFormFields from '../../Form/useFormFields'; +import useForm from '../../Form/useForm'; import useFieldType from '../../useFieldType'; import Error from '../../Error'; import { repeater } from '../../../../../fields/validations'; @@ -39,7 +39,7 @@ const Repeater = (props) => { const dataToInitialize = initialData || defaultValue; const [rows, dispatchRows] = useReducer(reducer, []); const { customComponentsPath } = useRenderedFields(); - const { getDataByPath } = useFormFields(); + const { getDataByPath } = useForm(); const path = pathFromProps || name; diff --git a/src/client/components/forms/field-types/rowReducer.js b/src/client/components/forms/field-types/rowReducer.js index 4faeeb5ddc..e21a5103fc 100644 --- a/src/client/components/forms/field-types/rowReducer.js +++ b/src/client/components/forms/field-types/rowReducer.js @@ -15,7 +15,7 @@ const reducer = (currentState, action) => { stateCopy[index].open = !stateCopy[index].open; return stateCopy; - case 'ADD': + case 'ADD': { stateCopy.splice(index + 1, 0, { open: true, key: uuidv4(), @@ -24,7 +24,7 @@ const reducer = (currentState, action) => { data.splice(index + 1, 0, initialRowData); - return stateCopy.map((row, i) => { + const result = stateCopy.map((row, i) => { return { ...row, data: { @@ -33,6 +33,10 @@ const reducer = (currentState, action) => { }; }); + return result; + } + + case 'REMOVE': stateCopy.splice(index, 1); return stateCopy; @@ -50,7 +54,6 @@ const reducer = (currentState, action) => { const movingRowState = { ...stateCopyWithNewData[index] }; stateCopyWithNewData.splice(index, 1); stateCopyWithNewData.splice(moveToIndex, 0, movingRowState); - return stateCopyWithNewData; }