【问题标题】:Update state with Reactjs DatePicker doesn't work使用 Reactjs DatePicker 更新状态不起作用
【发布时间】:2019-03-24 14:49:40
【问题描述】:

我使用 datepicker 添加项目并且它可以工作,但是当我尝试使用 datepicker 编辑/更新这些项目时,它不起作用!给我很多错误,例如:

  • 道具类型失败:提供给DatePickerstring类型的无效道具selected,应为object

  • 组件正在更改要控制的文本类型的不受控输入。输入元素不应从不受控切换到受控(反之亦然)。决定在组件的生命周期内使用受控输入元素还是不受控输入元素。

  • 道具类型失败:string 类型的无效道具 selected 提供给 Calendar/Month/Week/Day,应为 object

  • 未捕获的类型错误:无法读取未定义的属性“值”

并且输入为空,没有像预期的那样显示今天的日期,例如:

这是我的 EditProject 组件:

import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
import DatePicker from 'react-datepicker';
import moment from 'moment';

import './EditProject.css';
import 'react-datepicker/dist/react-datepicker.css';


class EditProject extends Component {
    constructor(props) {
        super(props);
        this.state = {
            project: {}
        }    
    }

    componentDidMount() {

        // console.log('PROPS ' + JSON.stringify(this.props));

        const { match: { params } } = this.props;


        fetch(`/dashboard/project/${params.id}/edit`)
            .then(response => {
                return response.json()
            }).then(project => {
                this.setState({
                    projectname: project.projectname,
                    typeofproject: project.typeofproject,
                    imageURL: project.imageURL,
                    startDate: project.startDate,
                    endDate: project.endDate
                })
            })
    }

    render() {
        const { match: { params } } = this.props;

        return (
            <div className='EditProject'>
                <h1 className='EditProject__title'>Edit</h1><h1 className='EditProject__projectname'>{this.state.projectname}</h1>
                <hr />
                <form method='POST' action={`/dashboard/project/${params.id}/edit?_method=PUT`}>
                    <div className='form-group container'>
                        <div className="input-group mb-3">
                            <div className="input-group-prepend">
                                <span className="input-group-text" style={{border:'none'}} id="basic-addon1">Project Name</span>
                            </div>
                            <input type='text' className='form-control input' placeholder='insert new project name' value={this.state.projectname} name='projectname' ref='projectname' onChange={(event) => this.setState({ projectname: event.target.value })} />
                        </div>
                    </div>
                    <div className='form-group container'>
                        <div className="input-group mb-3">
                            <div className="input-group-prepend">
                                <span className="input-group-text" style={{border:'none'}} id="basic-addon1">Type of Production</span>
                            </div>
                            <select className='form-control input' value={this.state.typeofproject} name='typeofproject' ref='typeofproject' onChange={(event) => this.setState({ typeofproject: event.target.value })}>
                                <option value='Film (Cinema)'>Film (Cinema)</option>
                                <option value='Film (TV)'>Film (TV)</option>
                                <option value='Film (series)'>Film (series)</option>
                                <option value='Short film'>Short film</option>
                                <option value='TV mini-series'>TV mini-series</option>
                                <option value='TV series'>TV series</option>
                                <option value='TV program'>TV program</option>
                                <option value='TV reporting'>TV reporting</option>
                                <option value='Vox Pop'>Vox Pop</option>
                                <option value='Advertisement Ad'>Advertisement Ad</option>
                                <option value='Documentary'>Documentary</option>
                                <option value='Documentary (TV)'>Documentary (TV)</option>
                                <option value='Documentary (series)'>Documentary (series)</option>
                                <option value='Commercial'>Commercial</option>
                                <option value='Video Clip'>Video Clip</option>
                                <option value='Live Video Clip TV'>Live Video Clip TV</option>
                                <option value='Photography Session'>Photography Session</option>
                            </select>
                        </div>
                    </div>
                    <div className='form-group container'>
                    <div className="input-group mb-3">
                        <div className="input-group-prepend">
                            <span className="input-group-text" style={{border:'none'}} id="basic-addon1">Start Date</span>
                        </div>
   // ================DATEPICKER HERE================
                        <DatePicker 
                            todayButton={"Today"}
                            dateFormat="DD/MM/YYYY"
                            selected={this.state.startDate}
                            value={this.state.startDate}
                            onChange={(event) => this.setState({ startDate: event.target.value })}
                        />
                    </div>
                </div>
                <div className='form-group container'>
                    <div className="input-group mb-3">
                        <div className="input-group-prepend">
                            <span className="input-group-text" style={{border:'none'}} id="basic-addon1">End Date</span>
                        </div>
                        <DatePicker
                            todayButton={"Today"}
                            dateFormat="DD/MM/YYYY"
                            selected={this.state.endDate}
                            value={this.state.endDate} 
                            onChange={(event) => this.setState({ endDate: event.target.value })}
                        />
                    </div>
                </div>
   // / ================DATEPICKER HERE================
                    <div className='form-group container'>
                        <div className="input-group mb-3">
                            <div className="input-group-prepend">
                                <span className="input-group-text" style={{border:'none'}} id="basic-addon1">Project Image URL</span>
                            </div>
                            <input type='text' className='form-control input 'placeholder='insert new project image URL' value={this.state.imageURL} name='imageURL' ref='imageURL' onChange={(event) => this.setState({ imageURL: event.target.value })} />
                        </div>
                    </div>                  
                    <div className='form-group container'>
                        <button type='submit' className='btn btn-default button--update'>Update</button>
                        <NavLink to={`/project/${params.id}/`} ><button type='submit' style={{ backgroundColor: '#b5b5b5' }} className='btn btn-default button--update'>Cancel</button></NavLink>
                    </div>
                </form>
            </div>
        );
    }
} 
export default EditProject;

非常感谢您的帮助!

【问题讨论】:

    标签: javascript reactjs datepicker react-datepicker


    【解决方案1】:

    startDate 不是设置为字符串吗?正如错误所说,我认为它应该是一个 Date 对象。

    另一个问题似乎是,当您渲染时,您的 fetch 和 setState(在 componentDidMount 中)没有完成。

    尝试添加一个状态变量(例如 isLoading),初始化为 true,并在所有 componentDidMount 行完成后将其设置为 false。现在在渲染中检查它,只要 isLoading 为 false,就会显示“正在加载”消息)。

    您还需要处理 fetch 失败的情况。在这种情况下,您根本无法呈现您的 datePicker。顺便说一句,我不确定 fetch 是否足够好。它在某些错误处理的情况下存在问题。我总是使用axios。

    【讨论】:

      【解决方案2】:

      来自您获取的日期需要转换为 Moment 日期。我不知道您的日期以什么格式返回,但如果它不是 ISO 8601 格式 (YYYY-MM-DD),那么您还需要在创建 Moment 对象时指定格式,以便将您的代码更改为其中之一以下:

      startDate: moment(project.startDate)
      startDate: moment(project.startDate, 'DD-MM-YYYY') //specify format that is relevant for your date string if it is not ISO8601
      

      组件提供的 onChange 事件处理程序返回选定的日期(它不像 普通 JS 事件处理程序)。因此,您将不会收到具有 event.target.value 的对象。相反,您将收到选择的日期,因此只需将参数的值设置为状态对象中的 startDate:

       onChange={(newDate) => this.setState({ startDate: newDate })}
      

      请注意,该值已经是时刻日期,因此不需要转换。

      然后您需要对 endDate 和 endDate 日期选择器执行同样的操作。

      另外请注意,除非您需要更改输入元素中实际显示的内容,否则实际上不需要设置 value 属性 - 通常您只需使用 selected 和 dateFormat 属性即可获得正确的输出(当然也可以设置这两个值并选择相同的东西会导致错误,因为前者需要一个字符串,而后者需要一个时刻对象)。

      关于受控到不受控的错误可能是由于您没有在构造函数中完全初始化您的状态 - 您应该在构造函数中将所有组件道具初始化为合理的东西,因为对获取的响应几乎肯定会在初始之后发生渲染为基于它的承诺。您在构造函数中的初始状态应如下所示(顺便说一下,项目属性似乎没有必要):

      this.state = {
              projectname: '',
              typeofproject: 'Film (Cinema)', //if you want a default selected otherwise leave as empty string
              imageURL: '',
              startDate: moment(),
              endDate: moment()
          }  
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        • 2020-08-02
        • 2018-12-30
        • 1970-01-01
        • 1970-01-01
        • 2021-09-17
        • 1970-01-01
        相关资源
        最近更新 更多