简体   繁体   中英

TypeError: Cannot read property 'name' of undefined error in a controlled-component

I'm trying to get a date as user input through a controlled component but always running into this error "TypeError: Cannot read property 'name' of undefined". This is the piece of code that's causing the error. I'm using the react-datepicker module to get the Date input as when I try to use the HTML input type="date" i'm unable to disable previousdates.

import React, {Fragment,useState,useEffect} from 'react';
import {Link,withRouter} from 'react-router-dom';
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import PropTypes from 'prop-types';
import {connect} from 'react-redux'; 
import {addTask} from '../../actions/task';
import { addDays } from 'date-fns';

const TaskForm = ({addTask}) => {
    const [formData,setFormData] = useState({
        description:'',
        due_at:'',
        toBeReminded:''
    })

    const onSubmit = e => {
        e.preventDefault();
        addTask(formData);
    }

    const onChange = e=>setFormData({...formData, [e.target.name]:e.target.value})
    const {description,due_at} = formData;
    return (
        <Fragment>
            <h1 className="large text-primary">
                New Task
            </h1>
            <form className="form my-1" onSubmit={e=>onSubmit(e)}>
                <div className="form-group">
                    <label htmlFor="descr">Description:</label><br/>
                    <input type="text" id="descr" placeholder="Task Description" name="description" value={description} onChange={e=> onChange(e)}/>
                </div>
                <div className="form-group">
                    <label htmlFor="due_date">Due Date for Task:</label><br></br>
                    <DatePicker id="due_date" minDate={addDays(new Date(), 1)} id="due_date" name="due_at" value={due_at} onChange={e=> onChange(e)} />
                </div>
                <div className="form-group">
                    <label htmlFor="reminder">Set Reminder:</label><br></br>
                    <input type="radio" id="yes" name="toBeReminded"  value="true" onClick={e=> onChange(e)}/>
                    <label htmlFor="yes">Yes</label><br/>
                    <input type="radio" id="no" name="toBeReminded" value="false" onClick={e=> onChange(e)}/>
                    <label htmlFor="no">No</label><br></br> 
                </div>
                <input type="submit" className="btn btn-dark my-1" value="Submit" />
                <Link className="btn btn-light my-1" to="/tasks">Go Back</Link>
            </form>
        </Fragment>
    )
}

TaskForm.propTypes = {
    addTask:PropTypes.func.isRequired
}

export default connect(null,{addTask})(TaskForm);

Looking at the docs for react-datepicker , it doesn't look like its onChange receives an event, but the date.

You should use a separate handler for the date change handler since they expect different signatures.

const onChange = e => setFormData({...formData, [e.target.name]:e.target.value})
const onDateChange = date => setFormData({...formData, due_at: date})

There's a lot of other solutions that would work if you really want to stick to one change handler, but I recommend just creating two like above.

But.. you could do something like this (I don't really recommend this):

const onChange = e => {
  if (typeof e === 'object') {
    setFormData({...formData, [e.target.name]:e.target.value})
  } else {
    setFormData({...formData, due_at: e})
  }
}

Or since you're declaring new inline functions already (its unnecessary by the way, just do onChange={onChange} unless you use the following approach) you could do this:

const onChange = (name, value) => setFormData({...formData, [e.target.name]:e.target.value})

// Regular inputs
onChange={e => onChange('input name', e.target.value)}

// Date input
onChange={date => onChange('input name', date)}

The bottom line is: you have to pay attention to what onChange is expected to receive. It will differ depending on the input type or the library implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM