1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
import { Formik, Form, Field, ErrorMessage } from 'formik' <Formik initialValues={{ username: '', password: '', rememberMe: true }} validate={values => { // handle errorrs let errors = {} if (!values.username) { errors.username = 'Required' } return errors }} onSubmit={(values, actions) => { // could accept such actions actions.resetForm() actions.setSubmitting(false); actions.setErrors({ onSubmit: 'the server unavailable' }); actions.setStatus({ msg: 'Set some arbitrary status or data' }); }} render={({ errors, status, touched, isSubmitting }) => ( <Form className="loginForm"> <div className="title"> <h2>To come in...</h2> </div> <div className="emailOrLogin" > <Field type="text" name="username" placeholder="Email or login" /> <ErrorMessage className="error" name="username" component="div" /> </div> <div className="password"> <Field type="password" name="password" placeholder="Password" /> <ErrorMessage className="error" name="password" component="div"/> </div> <div className="rememberMe"> <label> <Field type="checkbox" name="rememberMe" /> Remember me </label> </div> <ErrorMessage className="submitError" name="onSubmit" component="div"/> <button type="submit" disabled={isSubmitting}> Log in </button> {errors && errors.onSubmit && <div className="error">{errors.onSubmit}</div>} {status && status.msg && <div className="error">{status.msg}</div>} <div className='loginAndRegistration'> <Link to={`/${this.props.locale}/recover/`}>Recover forgotten password</Link> <Link to={`/${this.props.locale}/registration/`}>Registration</Link> </div> </Form> )} /> |
How to load a file on the server with the formik
https://hackernoon.com/formik-handling-files-and-recaptcha-209cbeae10bc
Formik doesn’t support such functionality, so you have to use this code
1 2 3 4 5 6 7 8 9 |
<input id="thumbnail" name="thumbnail" type="file" onChange={(event) => { setFieldValue("thumbnail", event.currentTarget.files[0]); return true; }} /> |
If we change input on the field it won’t work, we’ll get the error that tells that impossible to assign a file some data, we can assign only an empty string. The file should assign only programmatically. When we use pure input it is work.
then we can output the file to the form by using Thum component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
import React from 'react' class Thumb extends React.Component { state = { loading: false, thumb: undefined, file: undefined, }; shouldComponentUpdate(nextProps, nextState) { console.log('this.state = ', this.state); console.log('nextState = ', nextState); if (nextProps.file === this.props.file && this.state.loading === false) { return false } // if (nextState.loading && (nextState.thumb === this.state.thumb)) { // return false // } return true } componentWillReceiveProps(nextProps) { if(nextProps.file === this.props.file) { return; } if (!nextProps.file) { return; } this.setState({ loading: true }, () => { let reader = new FileReader(); reader.onloadend = () => { // console.log('reader.result = ', reader.result); this.setState({ loading: false, thumb: reader.result }); }; reader.readAsDataURL(nextProps.file); }); } render() { const { file } = this.props; const { loading, thumb } = this.state; if (!file) { return null; } if (loading) { return <p>loading...</p>; } return (<img src={thumb} alt={file.name} className="img-thumbnail mt-2" height={100} width={100} />); } } export default Thumb |
How to validate an input file with Formik
You have to call the function validateForm to validate form and validateField to validate field. In my case I’m going to validate all the form and I called the validateForm but it didn’t work, why? Because of me outputted the errors by using
1 |
<ErrorMessage className="error" name="thumbnail" component="div" /> |
So it won’t work, because of inside <ErrorMessage> is probably such a condition
1 2 3 |
{errors.thumbnail && touched.thumbnail && <div className="error">{errors.thumbnail}</div> } |
and my input file had such a code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<input id="thumbnail" name="thumbnail" type="file" onChange={(event) => { setFieldValue("thumbnail", event.currentTarget.files[0]); console.log('validateForm = ', validateForm); // validateForm() console.log('this.state = ', this.state); // return true; }} // onBlure=() /> |
by default setFieldValue will call Formik’s validate function, so you don’t need manually call validateForm, The problem was in that my touche.thumbnail was false and that’s why I don’t see outputting error messages. I added to onChange function the line
1 |
touched.thumbnail = true |
and everything was working
how it should be code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<input id="thumbnail" name="thumbnail" type="file" onChange={(event) => { setFieldValue("thumbnail", event.currentTarget.files[0]); touched.thumbnail = true console.log('validateForm = ', validateForm); // validateForm() console.log('this.state = ', this.state); // return true; }} // onBlure=() /> |
the end