Я добавляю проекты с помощью datepicker, и он работает, но когда я пытаюсь редактировать / обновлять эти проекты с помощью datepicker, не работает! дайте мне много ошибок, таких как:
Неудачный тип опоры: недопустимая опора selected
типа string
, предоставленная для DatePicker
, ожидаемая object
Компонент изменяет неконтролируемый ввод контролируемого текста типа. Элементы ввода не должны переключаться с неконтролируемого на управляемый (или наоборот). Выберите между использованием контролируемого или неконтролируемого элемента ввода на протяжении всего срока службы компонента.
Неудачный тип опоры: недопустимая опора selected
типа string
, предоставленная для Calendar/Month/Week/Day
, ожидаемая object
.
Uncaught TypeError: невозможно прочитать значение свойства undefined
и ввод пуст, не показывает сегодняшнюю дату, как предполагалось, пример здесь:
Вот мой компонент 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.info('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;
Спасибо большое за вашу помощь!
Разве для startDate не задана строка? Я предполагаю, что это должен быть объект Date, как говорится в ошибке.
Другая проблема, похоже, заключается в том, что при рендеринге ваши выборка и setState (в componentDidMount) не завершаются.
Попробуйте добавить переменную состояния (например, isLoading), инициализированную значением true, и установите для нее значение false, когда все строки componentDidMount будут выполнены. Теперь проверьте его в рендере и отобразите сообщение «загрузка», если isLoading имеет значение false).
Вам также необходимо позаботиться о ситуации, в которой происходит сбой выборки. В таком случае вы вообще не можете отобразить свой datePicker. Я не уверен, кстати, что эта выборка достаточно хороша. В некоторых случаях при обработке ошибок возникают проблемы. Я всегда использую аксиомы.
Даты, полученные из вашей выборки, необходимо преобразовать в дату Момент. Я не знаю, в каком формате возвращается ваша дата, но если он не в формате ISO 8601 (ГГГГ-ММ-ДД), вам также необходимо указать формат при создании объекта 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 и datepicker endDate.
Также обратите внимание, что на самом деле нет необходимости устанавливать свойство value, если вам не нужно изменять то, что на самом деле отображается во входном элементе - обычно вы можете добиться правильного вывода, используя только свойство selected и dateFormat (и, конечно, устанавливая оба значения и selected на то же самое приведет к ошибке, поскольку для первого требуется строка, а для второго - объект момента).
Ошибка в отношении контролируемого к неконтролируемому, вероятно, вызвана тем, что вы не полностью инициализировали свое состояние в своем конструкторе - вы должны инициализировать все свои свойства компонентов чем-то разумным в конструкторе, поскольку ответ на выборку почти наверняка произойдет после первоначального рендеринга, поскольку его на основе обещаний. Ваше начальное состояние в вашем конструкторе должно выглядеть примерно так (кстати, свойство проекта кажется ненужным):
this.state = {
projectname: '',
typeofproject: 'Film (Cinema)', //if you want a default selected otherwise leave as empty string
imageURL: '',
startDate: moment(),
endDate: moment()
}