From 07f0960c8cbc932fc88a16d49ed9b8900d93f8a0 Mon Sep 17 00:00:00 2001 From: William Petit Date: Tue, 25 Feb 2020 17:21:55 +0100 Subject: [PATCH] Ajout HOC WithForm --- frontend/src/components/UserForm.js | 131 ++++++++++------------------ frontend/src/components/WithForm.js | 73 ++++++++++++++++ frontend/src/pages/home.js | 4 +- 3 files changed, 120 insertions(+), 88 deletions(-) create mode 100644 frontend/src/components/WithForm.js diff --git a/frontend/src/components/UserForm.js b/frontend/src/components/UserForm.js index 6641ad1..d5391f4 100644 --- a/frontend/src/components/UserForm.js +++ b/frontend/src/components/UserForm.js @@ -1,118 +1,77 @@ -import { useState, useEffect } from 'react'; +import { useEffect } from 'react'; +import { WithForm } from './WithForm'; -const defaultData = { - username: '', - password: '', - passwordVerification: '' -}; - -const defaultErrors = { - username: { hasError: false, message: '' }, - password: { hasError: false, message: '' }, - passwordVerification: { hasError: false, message: '' }, -}; - -export function UserForm({ data = defaultData, errors = defaultErrors, onSubmit }) { - - const validators = { - username: (value, formData) => { - if (value === "") return { hasError: true, message: 'Le nom d\'utilisateur ne peut pas être vide !' } - return { hasError: false, message: '' }; - }, - password: (value, formData) => { - if (value === "") return { hasError: true, message: 'Le mot de passe ne peut pas être vide !' } - if (value !== formData.passwordVerification) return { hasError: true, message: 'Vos deux mots de passe sont différents !' } - return { hasError: false, message: '' }; - }, - passwordVerification: (value, formData) => { - if (value !== formData.password) return { hasError: true, message: 'Vos deux mots de passe sont différents !' } - return { hasError: false, message: '' }; - } - }; - - const [ formErrors, setFormErrors ] = useState({ ...defaultErrors, ...errors }); - const [ formData, setFormData ] = useState({ ...defaultData, ...data }); +export function UserForm({ form, onSubmit }) { useEffect(() => { - setFormErrors(formErrors => { - return { ...formErrors, ...errors }; - }); - }, [errors]); - - useEffect(() => { - setFormData(formData => { - return { ...formData, ...data }; - }); - }, [data]); - - - const hasFormErrors = Object.values(formErrors).reduce((hasFormErrors, fieldError) => { - return hasFormErrors || fieldError.hasError; - }, false); - const { username, password, passwordVerification } = formData; - - const onInputChange = evt => { - const name = evt.target.name; - const value = evt.target.value; - setFormData(formData => { - return { ...formData, [name]: value }; - }); - } - - useEffect(() => { - Object.keys(formData).forEach(name => { - if (typeof validators[name] !== 'function') return; - const value = formData[name]; - const result = validators[name](value, formData); - setFormErrors(formErrors => { - return { ...formErrors, [name]: result }; - }); - }); - }, [formData]); - - const dispatchSubmit = evt => { - evt.preventDefault(); - if (hasFormErrors) return; - if (typeof onSubmit === 'function') onSubmit(formData); - }; + console.log(form.valid, form.submitted); + if (form.valid && form.submitted) onSubmit(form.data); + }, [form.valid, form.submitted]); return ( -
+
- +
{ - formErrors.username.hasError ? -

{formErrors.username.message}

+ form.hasError('username') ? +

{form.error('username')}

: null }
- +
{ - formErrors.password.hasError ? -

{formErrors.password.message}

+ form.hasError('password') ? +

{form.error('password')}

: null }
- +
{ - formErrors.passwordVerification.hasError ? -

{formErrors.passwordVerification.message}

+ form.hasError('passwordVerification') ? +

{form.error('passwordVerification')}

: null }
- +
); }; + +const validators = { + username: (value, formData) => { + if (!value) return { hasError: true, message: 'Le nom d\'utilisateur ne peut pas être vide !' } + return { hasError: false, message: '' }; + }, + password: (value, formData) => { + if (!value) return { hasError: true, message: 'Le mot de passe ne peut pas être vide !' } + if (value !== formData.passwordVerification) return { hasError: true, message: 'Vos deux mots de passe sont différents !' } + return { hasError: false, message: '' }; + }, + passwordVerification: (value, formData) => { + if (value !== formData.password) return { hasError: true, message: 'Vos deux mots de passe sont différents !' } + return { hasError: false, message: '' }; + } +}; + +export const ExtendedUserForm = WithForm(validators)(UserForm); diff --git a/frontend/src/components/WithForm.js b/frontend/src/components/WithForm.js new file mode 100644 index 0000000..351a039 --- /dev/null +++ b/frontend/src/components/WithForm.js @@ -0,0 +1,73 @@ +import { useState, useEffect } from 'react'; + +export function WithForm(validators) { + + return function(Component) { + + return function WithFormWrapper(props) { + + const [ formData, setFormData ] = useState({}); + const [ formErrors, setFormErrors ] = useState({}); + const [ submitted, setSubmitted ] = useState(false); + + const validateField = (name) => { + if (typeof validators[name] !== 'function') 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]); + + 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 ; + }; + } +} + +// connect(mapStateToProps)(MyComponent) \ No newline at end of file diff --git a/frontend/src/pages/home.js b/frontend/src/pages/home.js index 4960c9b..a0512e8 100644 --- a/frontend/src/pages/home.js +++ b/frontend/src/pages/home.js @@ -1,13 +1,13 @@ import React from 'react' import Page from './page'; -import { UserForm } from '../components/UserForm'; +import { ExtendedUserForm as UserForm } from '../components/UserForm'; export default class HomePage extends React.PureComponent { render() { const onUserFormSubmit = formData => { - console.log(formData); + console.log(formData); }; return (