sickdyd/react-search-autocomplete

How to use ReactSearchAutocomplete with formik and yup

Opened this issue · 0 comments

I want to use ReactSearchAutocomplete with formik and yup how to validate with yup and how to render the component as children of form field.

Package.json

{
  "name": "react",
  "version": "1.0.0",
  "description": "React example starter project",
  "keywords": [
    "react",
    "starter"
  ],
  "main": "src/index.js",
  "dependencies": {
    "bootstrap": "5.2.0",
    "formik": "2.2.9",
    "react": "17.0.0",
    "react-bootstrap": "2.5.0",
    "react-dom": "17.0.0",
    "react-scripts": "4.0.0",
    "react-search-autocomplete": "7.2.2",
    "yup": "0.32.11"
  },
  "devDependencies": {
    "@babel/runtime": "7.13.8",
    "typescript": "4.1.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

Codesandbox example
(https://codesandbox.io/s/amazing-diffie-o4hbod)

Visit this codesandbox example for reference
https://codesandbox.io/s/amazing-diffie-o4hbod

To Reproduce

import React, { useState } from "react";
import { Container, Form, Row } from "react-bootstrap";
import { Formik, Field } from "formik";
import * as Yup from "yup";
import { Button } from "react-bootstrap";
import SearchComponent from "./SearchComponent";

const FormComponent = () => {
  const [searchString, setSearchString] = useState("");

  const schema = Yup.object().shape({
    comment: Yup.string().required("Comment is required"),
    assignment: Yup.array()
      .min(1, "At least one option is required")
      .required()
      .nullable()
  });

  return (
    <Container className="my-3">
      <Row>
        <Formik
          validationSchema={schema}
          onSubmit={(values) => {
            console.log(values);
          }}
          initialValues={{
            comment: "",
            assignment: {}
          }}
        >
          {({
            handleSubmit,
            handleChange,
            handleBlur,
            values,
            touched,
            isValid,
            errors
          }) => (
            <Form noValidate onSubmit={handleSubmit}>
              <Form.Group
                controlId="validationFormik03"
                className="position-relative mb-3"
              >
                <Form.Control
                  as="textarea"
                  rows={3}
                  placeholder={"Comment"}
                  name="comment"
                  value={values.comment}
                  onChange={handleChange}
                  isInvalid={touched.comment && errors.comment}
                />

                <Form.Control.Feedback type="invalid" className="text-danger">
                  {errors.comment}
                </Form.Control.Feedback>
              </Form.Group>
              <Form.Group>
                {/* <Form.Control
                  // as="select"
                  name="assignment"
                  component={
                    <SearchComponent
                      searchString={searchString}
                      setSearchString={setSearchString}
                    />
                  }
                  isInvalid={touched.assignment && errors.assignment}
                /> */}
                {
                  <SearchComponent>
                    <Field
                      placeholder={"Comment"}
                      name="assignment"
                      value={values.assignment}
                      onChange={handleChange}
                      isInvalid={touched.assignment && errors.assignment}
                    />
                  </SearchComponent>
                }
                <Form.Control.Feedback type="invalid" className="text-danger">
                  {errors.assignment}
                </Form.Control.Feedback>
              </Form.Group>
              <div className=" float-right mt-3">
                <Button variant="primary" type="submit">
                  Submit
                </Button>
              </div>
            </Form>
          )}
        </Formik>
      </Row>
    </Container>
  );
};

export default FormComponent;

SearchComponent.js

import React from "react";
import { ReactSearchAutocomplete } from "react-search-autocomplete";
const SearchComponent = ({
  // field, // { name, value, onChange, onBlur }
  // form: { touched, errors }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
  ...props
}) => {
  const { searchString, setSearchString, children } = props;
  const items = [
    {
      id: 0,
      name: "Cobol"
    },
    {
      id: 1,
      name: "JavaScript"
    },
    {
      id: 2,
      name: "Basic"
    },
    {
      id: 3,
      name: "PHP"
    },
    {
      id: 4,
      name: "Java"
    }
  ];
  const handleOnSearch = (string, results) => {
    console.log(string, results);
  };
  const handleOnClear = () => {
    setSearchString("");
  };
  const handleOnSelect = (item) => {
    console.log(item);
  };
  return (
    <>
      <ReactSearchAutocomplete
        items={items}
        onSearch={handleOnSearch}
        onClear={handleOnClear}
        onSelect={handleOnSelect}
        inputSearchString={searchString}
        autoFocus
      >
        {children}
      </ReactSearchAutocomplete>
    </>
  );
};
export default SearchComponent;

Expected behavior
Both comment and search fields should be validated with yup if we click on submit without selecting any options then error message should be shown same as comment field. If we enter comment and select one option and then if we click on submit we should get values object on formik onsubmit.

Screenshots
Screenshot 2022-08-10 163129

Additional context
Add any other context about the problem here.