Setting the value of DatePicker (from antd) in react-hook-form

Mel picture Mel · Nov 13, 2019 · Viewed 7.4k times · Source

I'm trying to figure out how to use the DatePicker from antd with react-hook-form.

Currently, my attempt is:

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import useForm from "react-hook-form";
import { withRouter } from "react-router-dom";
import { useStateMachine } from "little-state-machine";
import updateAction from "./updateAction";
import { Input as InputField, Form, Button, DatePicker, Divider, Layout, Typography, Skeleton, Switch, Card, Icon, Avatar } from 'antd';
import Select from "react-select";


const { Content } = Layout 
const { Text, Paragraph } = Typography;
const { Meta } = Card;
const { MonthPicker, RangePicker, WeekPicker } = DatePicker;



  const Team = props => {
    const { register, handleSubmit, setValue, errors } = useForm();
    const [ dueDate, setDate ] = useState(new Date());
    const [indexes, setIndexes] = React.useState([]);
    const [counter, setCounter] = React.useState(0);
    const { action } = useStateMachine(updateAction);
    const onSubit = data => {
      action(data);
      props.history.push("./ProposalBudget");
    };

    
    // const handleChange = dueDate => setDate(date);
    const handleChange = (e) => {
      setValue("dueDate", e.target.value);
    }


  const onSubmit = data => {
    console.log(data);
  };

  const addMilestone = () => {
    setIndexes(prevIndexes => [...prevIndexes, counter]);
    setCounter(prevCounter => prevCounter + 1);
  };

  const removeMilestone = index => () => {
    setIndexes(prevIndexes => [...prevIndexes.filter(item => item !== index)]);
  };

  const clearMilestones = () => {
    setIndexes([]);
  };

  useEffect(() => {
    register({ name: dueDate }); // custom register antd input
  }, [register]);

Note: i have also tried name: {${fieldName}.dueDate - that doesn't work either.

  return (
    <div>
        <HeaderBranding />
        <Content
          style={{
            background: '#fff',
            padding: 24,
            margin: "auto",
            minHeight: 280,
            width: '70%'
          }}
        >
        <form onSubmit={handleSubmit(onSubit)}>
        
          {indexes.map(index => {
            const fieldName = `milestones[${index}]`;
            return (
              <fieldset name={fieldName} key={fieldName}>
                <label>
                  Title:
                  <input
                    type="text"
                    name={`${fieldName}.title`}
                    ref={register}
                  />
                </label>

                <label>
                  Description:
                  <textarea
                    rows={12}
                    name={`${fieldName}.description`}
                    ref={register}
                  />
                </label>
                <label>When do you expect to complete this milestone? <br />
                
                  
                <DatePicker 
                  selected={ dueDate } 
                  // ref={register}
                  InputField name={`${fieldName}.dueDate`} 
                  onChange={handleChange(index)}

                  //onChange={ handleChange }
                   >
                  <input 
                  type="date" 
                  name={`${fieldName}.dueDate`} 
                  inputRef={register}
                />
                </DatePicker>
              
                </label>
                
                <Button type="danger" style={{ marginBottom: '20px', float: 'right'}} onClick={removeMilestone(index)}>
                  Remove this Milestone
                </Button>
              </fieldset>
            );
          })}

          <Button type="primary" style={{ marginBottom: '20px'}} onClick={addMilestone}>
            Add a Milestone
          </Button>
          <br />
          <Button type="button" style={{ marginBottom: '20px'}} onClick={clearMilestones}>
            Clear Milestones
          </Button>
          <input type="submit" value="next - budget" />
        </form>
       </Content>
       
      </div>  
  );
};

export default withRouter(Team);

This generates an error that says: TypeError: Cannot read property 'value' of undefined

setValue is defined in handleChange.

I'm not clear on what steps are outstanding to get this datepicker functioning. Do I need a separate select function?

Has anyone figured out how to plug this datepicker in?

I have also tried:

const handleChange = (e) => {
      setValue("dueDate", e.target.Date);
    }

and I have tried:

const handleChange = (e) => {
      setValue("dueDate", e.target.date);
    }

but each of these generations the same error

Answer

Bill picture Bill · Nov 24, 2019

I have built a wrapper component to work with external controlled component easier: https://github.com/react-hook-form/react-hook-form-input

import React from 'react';
import useForm from 'react-hook-form';
import { RHFInput } from 'react-hook-form-input';
import Select from 'react-select';

const options = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
  { value: 'vanilla', label: 'Vanilla' },
];

function App() {
  const { handleSubmit, register, setValue, reset } = useForm();

  return (
    <form onSubmit={handleSubmit(data => console.log(data))}>
      <RHFInput
        as={<Select options={options} />}
        rules={{ required: true }}
        name="reactSelect"
        register={register}
        setValue={setValue}
      />
      <button
        type="button"
        onClick={() => {
          reset({
            reactSelect: '',
          });
        }}
      >
        Reset Form
      </button>
      <button>submit</button>
    </form>
  );
}

try this out, let me know if it makes your life easier with AntD.