Utilizing Formik alongside Yup and React-select for enhanced validation

Currently, I am implementing form validation in a React project using both Yup and Formik. The challenge I am facing is with validating a react-select element within the form. To achieve this, I am utilizing the validationSchema property of Formik to validate the form upon value changes. The specific issue I'm encountering is that while the select field is functioning correctly, the validation error message persists even after correction. My main query revolves around how to effectively validate the select field using my current method.

Below is an abbreviated version of the code sample I am working on.

<!-- Code Sample Goes Here -->

You can also view the live example on Codesandbox:

https://codesandbox.io/s/throbbing-shadow-6f6yw?fontsize=14

Note: This is one of my early experiences with Reactjs.

Answer №1

Update

handleChange("year")(selectedOption.value);

In order to successfully update the Formik value for the year field, it is necessary to call the handleChange() function with the selected option's value. This approach allows for updating the Formik state as intended.

An easy way to identify and resolve such issues is by outputting the Formik props using the following code snippet:

<pre>{JSON.stringify(props, null, 2)}</pre>

For a practical demonstration, refer to this sandbox example. By relying solely on the Formik state, you can eliminate the need for a custom year state. It is advisable to manipulate values using only the Formik state, ensuring that when saving, only the year component needs to be extracted due to react-select utilizing the entire object by default.

Answer №2

To trick Formik into recognizing this as an event, you can use the handleChange function provided by Formik. This method can also be applied to other input field types like react-color or a datepicker.

validationSchema = yup.object({
  year_value: yup.object().required('Year value is required.')
})
<Select 
  className=""
  name="year_value"
  id="year_value"
  placeholder='Choose year value'
  value={values.year_value}
  onBlur={handleBlur}
  onChange={selectedOption => {
    let event = {target: {name: 'year_value', value: selectedOption}}
    handleChange(event)
  }}
  onBlur={() => {
    handleBlur({target: {name: 'year_value'}});
  }}
  options={yearOptions}
/>

Answer №3

If anyone is seeking solutions for this issue in the future, here's a different method to retrieve the selected value as a string from react-select while still utilizing Yup for validation on the select input:

By using the helpers function from useField(), you can manage the value, touched state, and errors of a "Field". This is particularly useful when dealing with elements like react-select that are not traditional inputs.

function EnhancedSelectComponent(...props) {
  const [field, meta, helpers] = useField(name="mySelectInput"); // You can also pass 'props' into useField if they contain a name attribute
  const { setValue, setTouched, setError } = helpers;

  const updateFieldProps = (selectedOption) => {
      setValue(selectedOption.value);
      setTouched(true);
      setError(undefined);
  }

  return (
        <Select onChange={selectedOption => updateFieldProps(selectedOption)} />
  );
};

Answer №4

To address my issue, I implemented the following solution:

Firstly, include the necessary imports at the beginning of your code:

import Select from 'react-select';
import { Formik, Form, Field } from 'formik';

Next, integrate this code snippet into your JSX render section:

<Formik
      initialValues={initialUserAddData}
      validationSchema={addUserValidationSchema}
      onSubmit={handleAddUser}
    >
      {({ errors }) => (
        <Form className="add-edit-user-form">
          <Field name="department">
            {({ field, form }) => (
               <Select
                 className="select-wrap"
                 classNamePrefix="select-box"
                 options={department}
                 onChange={(selectedOption) =>
                     form.setFieldValue(
                       'department',
                       selectedOption.value,
                      )
                    }
               />
            )}
         </Field>
         {errors.department && (
           <span className="error">{errors.department}</span>
         )}
       </Form>
      )}
 </Formik>

This example showcases how to utilize react-select in conjunction with formik to update values during form validation. Alternatively, you can also employ the useFormik hook for similar functionality, although this offers a distinct approach.

Answer №5

If I were to choose, I'd opt for Formik select over react select in the following manner:

    const initialValues = {
        firstName: "",
        lastName: ""
    };

    const validationSchema = Yup.object().shape({
      firstName: Yup.string().required("First name is required"),
      lastName: Yup.string().required("Last name is required")
    });

<Field as="select" name="lastName" id="lastName">
    <option value="" label="">
    Select Your Last Name{" "}
    </option>
    {lastNameOptions.map(item => 
       <option value={item.value} label={item.label}>{item.value}</option>
   )} 
</Field>

Utilize the map function on the options array to generate options dynamically

Answer №6

If you're still on the hunt for a solution, look no further. This should do the trick.

Start by creating your own custom component using the Select component.

import Select from "react-select";

export default function CustomSelect({ onChange, options, value, name, className = "" }) {
    const defaultValue = (options, value) => {
        return options ? options.find((option) => option.value === value) : "";
    };

    return (
        <div>
            <Select
                className={className}
                name={name}
                value={defaultValue(options, value)}
                onChange={(value) => {
                    onChange(value);
                }}
                options={options}
            />
        </div>
    );
}

Next, import your custom component and use it as shown below. Be sure to utilize setFieldTouched and setFieldValue from formik props to properly set and validate the form.

<CustomSelect
   name="name"
   value={"value"}
   options={options}
   onChange={(option) => {
   setFieldTouched("name", true);
   setFieldValue("name", option.value);
   }}
/>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Building a Skybox Material using Shader Graph in Unity3D

I have successfully created a material using ShaderGraph and I am trying to assign it as a skybox material. However, I am facing an issue where when I assign it to the environment -> skybox material in the light settings, it only gets assigned to one side ...

Mastering the art of theming components using styled-components and Material-UI

Can you integrate the Material-UI "theme"-prop with styled-components using TypeScript? Here is an example of Material-UI code: const useStyles = makeStyles((theme: Theme) => ({ root: { background: theme.palette.primary.main, }, })); I attemp ...

Having trouble viewing the images that were uploaded with Multer using React, Node.js, Sequelize, and PostgreSQL

Is there a way to enable users to click on the default avatar and upload their own image? Although I can successfully upload files to the database, I'm facing issues in accessing them from the client side. It seems like I might not be storing them cor ...

The error message "TypeError: Trying to access properties of an undefined object (reading '800')" is being displayed

Every time I launch my application, I encounter the error message: "TypeError: Cannot read properties of undefined (reading '800')". import React, { useState } from 'react'; import { Menu, MenuItem, Avatar, Box, ThemeProvider} ...

What is the best way to display a downshift + popper above a material-ui dialog?

After successfully implementing an autocomplete multi-select field using Downshift with Popper from the Material-UI demo, I encountered a problem when trying to reuse the component within a Material-UI Dialog. The Popper ended up appearing behind the mask ...

Day Change Triggers React [Native] View Update

I've been working on a React Native component that needs to update itself when the day changes, regardless of user interaction. Is there another method besides using setInterval for this task? If I use setTimeout in my viewDidLoad function with the n ...

Next.js fails to load TailwindCSS

I am in the process of developing an app using tailwindcss and next.js First, I started creating the nextjs app, then I executed these commands: npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p Following that, I made adjustments t ...

Having issues with stripe payments in my ReactJS application

I've encountered an issue while attempting to process a credit card payment using Stripe. Here's the code snippet I'm currently working with: import StripeCheckout from "react-stripe-checkout" // import confirmPayment from 'st ...

Switch up primary and secondary color schemes with the Material UI Theme swap

Exploring Material UI themes for React JS is a new venture for me. I am facing a scenario where I need to dynamically change the theme colors (Primary & Secondary) based on a selected type from a dropdown menu. Similar to the color customization options av ...

Can we include an option to display all pages in one row on a single page?

Is it possible to include an option to display all rows alongside the current options of 10, 15, and 100? I've been unable to locate this feature in the documentation: Check out the Codesandbox example: https://codesandbox.io/s/muidatatables-custom-t ...

How do I insert commas between cells in a React Material-Table populated from a fetched array?

Using Material Table to manage workstations, I encounter arrays in the data that are automatically displayed in cells without commas. See current behavior Here's what I'm aiming for I don't want to override the entire cell component or mo ...

A strategy for targeting the Material UI TextField with useRef hooks while a button is activated

I am encountering a similar issue as described in this Stack Overflow post, however, the solutions provided did not resolve my problem. The situation involves disabled textfields. When the edit profile button is clicked, the disabled state for the account ...

Transfer the updated variable from a static JavaScript file to Next.js

I am facing a challenge with a conditional render in my component. I am unable to display the value of a variable. In one file, I have all my functions that I export in index.js import FunctionServices from "../services/functionServices" export ...

combining the package.json files of the client and server into a single file

I need assistance with merging server-side code (in nodejs) and client-side code (with react) into a single package.json file. The server file is located in the project root directory, while the client-side code resides in the /client folder along with oth ...

When integrating react-hook-form with Material-UI TextField in a form, an error occurs stating that "TypeError: e.target is undefined" when

Hey there, I stumbled upon something fascinating and could really use some assistance. Every time I attempt to perform an onChange, I run into the following error: TypeError: e.target is undefined. Here's a snippet of my setup: import React, { useE ...

The user fails to be redirected following wallet authentication in NextJS

Can someone help me figure out how to redirect the user to the onboard page after successfully connecting to their wallet? Web3Button doesn't seem to be returning anything and I'm stuck. import React, { useEffect } from "react"; import ...

The directory "Users/node_modules/crypto-browserify" is not a valid directory in react

After discovering the package crypto-browserify on GitHub, I attempted to integrate it into my React Native project. Following the command npm install --save crypto-browserify, I then imported it using var crypto = require('crypto-browserify');. ...

Animated collapse with margin effect in Material-UI

I have been utilizing the MUI-Collapse component to display collapsible content within a list. I am looking to add vertical spacing between the Collapse components in the list, but I do not want the spacing to remain when the Collapse is collapsed. I am ha ...

Session is being established by Express/Passport, however, the cookie is not being transmitted to the

Currently, I have a project running with React on the client side and Node.js on the server side. Client side (React app) - http://localhost:3000 Server side (Node.js) - http:..localhost:5000 My focus at the moment is on implementing user authentication ...

Exploring ways to implement authentication by leveraging Redux state variables

After logging in, I have utilized a state variable in Redux that changes. How can this be used to determine if the user is logged in or not? Upon refreshing the page, it automatically redirects to the login page. if(authError === "") return <R ...