Nipuna Chandimal
Nipuna Chandimal

Reputation: 77

Formic always shows that form is invalid

Here I used formic with yup . Even I defied some schema for validation and even the values in the inputs full fill that rules formic in combination with YUP always says that the form is invalid even the form values are valid. I am a beginner. So I would be much thankful to you if you could provide some in-depth answer.

Thank you

import React, { useEffect, useState } from 'react'
import './index.css'
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
import axios from 'axios'


const Inedex = () => {

const [projects, setProjects] = useState([])
const [memebers, setMemebers] = useState([])

const [formData, setFormData] = useState({
    projectId: "",
    title: "",
    actualOutcomes: "",
    expectedOutcomes: ""
})


const setData = (key, value) => {
    setFormData({ ...formData, [key]: value })
    console.log(formData, { key, value })
}


useEffect(() => {
    getProjects();
}, [])

const getProjects = () => {
    axios.get("http://localhost:5000/project/all/names").then(res => {
        console.log(res.data)
        setProjects([...res.data])
    })
}

const handleProjectChange = (value) => {
    setData("projectId", value);
    axios.post("http://localhost:5000/project/roles", {
        "projectId": value,
        "role": "DEV"
    }).then(res => {
        console.log(res.data)
        setMemebers(res.data)
    })

}

const submitForm = (values) => {
    console.log(values);
};

const initialValues = {
    project:"",
    developer:"",
    email: "",
    title: "",
    project: "",
    developer: "",
    title: "",
    actualOutcomes: "",
    expectedOutcomes: ""
};


const DynamicProjectOptions = () => {
    return (
        projects.map(project => {
            return (
                <option value={project.id} key={projects.name} >{project.name}</option>
            )
        })
    )
}


const DynamicMembers = () => {
    return (
        memebers.map(memeber => {
            return (
                <option value={memeber.id} key={memeber.name} >{memeber.name}</option>
            )
        })
    )
}


const signInSchema = Yup.object().shape({
    project: Yup.string().min(1, 'Too Short!').required("Project is required"),
    developer: Yup.string().min(1, 'Too Short!').required("Developer is required"),
    title: Yup.string().min(5, 'Too Short!').required("Title is required"),
    actualOutcomes: Yup.string().min(5, 'Too Short!').required("Actual outcomes is required"),
    expectedOutcomes: Yup.string().min(5, 'Too Short!').required("Expected outcomes is required"),

});



return (
    <Formik
        initialValues={initialValues}
        validationSchema={signInSchema}
        onSubmit={(values) => alert(values)}
    >
        {({ errors, touched, isValid, dirty }) => {

            return (<Form>
                <div className="container">
                    <h2>Report a bug</h2>

                    {/* Project  */}

                    {isValid}
                    <div className="form-row">
                        <label htmlFor="project">Project</label>
                        <Field
                            name="project"
                            component="select"
                            id="project"
                            className={(errors.email && touched.email ? "is-invalid" : null) + " form-control "}
                            onChange={e => { handleProjectChange(e.target.value) }}
                            value={formData.projectId}
                        >
                            <DynamicProjectOptions />
                        </Field>

                        {JSON.stringify(formData.selectedProject)}
                        <ErrorMessage name="project" component="span" className="invalid-feedback" />
                    </div>


                    {/* Developer  */}
                    <div className="form-row">
                        <label htmlFor="developer">Developer</label>

                        <Field
                            name="developer"
                            component="select"
                            id="developer"
                            className={(errors.email && touched.email ? "is-invalid" : null) + " form-control "}
                        >
                            <DynamicMembers />
                        </Field>

                        <ErrorMessage name="developer" component="span" className="invalid-feedback" />
                    </div>



                    <div className="form-row">
                        <label htmlFor="title">Title</label>
                        <Field
                            type="text"
                            name="title"
                            id="email"
                            className={(errors.email && touched.email ? "is-invalid" : null) + " form-control "}
                            onChange={(e) => { setData("title", e.target.value) }}
                            value={formData.title}
                        />
                        <ErrorMessage name="title" component="span" className="invalid-feedback" />
                    </div>


                    <div className="form-row">
                        <label htmlFor="email">Actual outcomes</label>
                        <Field
                            type="text"
                            name="actualOutcomes"
                            id="actualOutcomes"
                            className={(errors.email && touched.email ? "is-invalid" : null) + " form-control "}
                            onChange={(e) => { setData("actualOutcomes", e.target.value) }}
                            value={formData.actualOutcomes}
                        />
                        <ErrorMessage name="actualOutcomes" component="span" className="invalid-feedback" />
                    </div>

                    <div className="form-row">
                        <label htmlFor="email">Expected outcomes</label>
                        <Field
                            type="text"
                            name="expectedOutcomes"
                            id="expectedOutcomes"
                            className={(errors.email && touched.email ? "is-invalid" : null) + " form-control "}
                            onChange={(e) => { setData("expectedOutcomes", e.target.value) }}
                            value={formData.expectedOutcomes}
                        />
                        <ErrorMessage name="expectedOutcomes" component="span" className="invalid-feedback" />
                    </div>

                    {JSON.stringify({dirty , isValid , touched})}
                    {/* {JSON.stringify(Object.keys(errors))} */}
                    <button
                        type="submit"
                        className={!(dirty && isValid) ? "disabled-btn" : ""}
                        disabled={!(dirty && isValid)}
                    >
                        Sign In
                    </button>
                </div>
            </Form>
            );
        }}
    </Formik>
      );
     };

   export default Inedex;

Upvotes: 0

Views: 763

Answers (1)

Anuja
Anuja

Reputation: 1038

Check sandbox, https://codesandbox.io/s/sharp-leftpad-0j792?file=/src/App.js

multiple issues here, <Field/> component automatically manages onChange to set to formik state,

  1. you dont need to manage form state separately
  2. you have to call setFieldValue if you give custom onChange function
  3. you dont need to pass value to <Field/> component, it is done from within.

Upvotes: 1

Related Questions