react-logo/frontend/src/components/WithForm.js

84 lines
2.7 KiB
JavaScript

import React from 'react';
import { useState, useEffect } from 'react';
export function WithForm(validators) {
return function(Component) {
return function WithFormWrapper({ errors, ...props }) {
const [ formData, setFormData ] = useState({});
const [ formErrors, setFormErrors ] = useState(errors || {});
const [ submitted, setSubmitted ] = useState(false);
const validateField = (name) => {
if (typeof validators[name] !== 'function') {
setFormErrors(formErrors => {
return { ...formErrors, [name]: { hasError: false, message: '' } };
});
return
};
const value = formData[name];
const result = validators[name](value, formData);
setFormErrors(formErrors => {
return { ...formErrors, [name]: result };
});
}
useEffect(() => {
Object.keys(formData).forEach(validateField);
}, [formData]);
useEffect(() => {
setSubmitted(false);
}, [submitted]);
useEffect(() => {
setFormErrors(errors || {});
}, [errors]);
const form = {
field: (name, defaultValue) => {
return name in formData ? formData[name] : defaultValue;
},
onChange: (name) => {
return (evt) => {
const value = evt.target.value;
setFormData(formData => {
return { ...formData, [name]: value };
});
};
},
hasError: (name) => {
return name in formErrors ? formErrors[name].hasError : false;
},
error: (name) => {
return name in formErrors ? formErrors[name].message : '';
},
onSubmit: (evt) => {
evt.preventDefault();
Object.keys(validators).forEach(validateField);
setSubmitted(true);
},
valid: !Object.values(formErrors).reduce((hasErrors, fieldError) => {
return hasErrors || fieldError.hasError;
}, false),
data: { ...formData },
errors: { ...formErrors },
submitted,
};
return <Component form={form} {...props} />;
};
}
}
// connect(mapStateToProps)(MyComponent)