I have a list of students on my page. When I click on some student, a form should appear with input element for all of student's properties. When form is submitted, student's properties should change. The problem is when I want to set initial value of input elements as a properties of a current selected student. The value of input elements is filled with properties of a current student, but when I try to type something in that input, it's value does not change. Code of Parent component
class App extends Component {
constructor(props){
super(props);
this.state = {
students :listStudents(),
visible: false,
index: 0,
student: listStudents()[0]
};
this.onClick = this.onClick.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onNewStudentSubmit = this.onNewStudentSubmit.bind(this);
}
onClick(index){
if(this.state.visible){
this.setState({
visible: false,
index: 0
});
}
else {
let student1 = this.state.students
.filter(s => s.index === index);
this.setState({
visible: true,
index: index,
student: student1[0]
});
}
}
onSubmit(student){
let list = this.state.students
.map(s => {
if(s.index === this.state.index)
return student;
return s;
});
this.setState({
students : list,
visible: false
});
}
render() {
return (
<div className="App">
<StudentsList students={this.state.students} onClick={this.onClick}/>
<EditStudentDetails student={this.state.student} visible={this.state.visible} onSubmit={this.onSubmit}/>
<CreateStudent onSubmit={this.onNewStudentSubmit}/>
</div>
);
}
}
export default App;
onClick function changes selected student and stores it in state.student. onSubmit function is triggered when the student's editing form is submitted. Render returns the list of all students and a editing component which can be visible or not. Below is code of my editing component.
import React from 'react';
class EditStudentDetails extends React.Component{
constructor(props){
super(props);
this.state = {
name: "",
surname: "",
index : "",
class : "",
visible: ""
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleNameChange = this.handleNameChange.bind(this);
this.handleSurnameChange = this.handleSurnameChange.bind(this);
this.handleClassChange = this.handleClassChange.bind(this);
this.handleIndexChange = this.handleIndexChange.bind(this);
}
handleSubmit(e){
const student = {
name: this.state.name,
surname: this.state.surname,
index : this.state.index,
class : this.state.class
};
this.props.onSubmit(student);
e.preventDefault();
}
handleNameChange(e){
const newName = e.target.value;
this.setState({
name: newName
});
}
handleSurnameChange(e){
const newName = e.target.value;
this.setState({
surname: newName
});
}
handleIndexChange(e){
const newIndex = e.target.value;
this.setState({
index: newIndex
});
}
handleClassChange(e){
const newClass = e.target.value;
this.setState({
class: newClass
});
}
render(){
const type = this.props.visible ? {display: 'block'} : {display: 'none'} ;
return(
<div style={type}>
<form className="form-group" onSubmit={this.handleSubmit}>
Име
<input className="Name" type="text" onChange={this.handleNameChange} value={this.props.student.name}/>
Презиме
<input className="Surname" type="text" onChange={this.handleSurnameChange} value={this.props.student.surname}/>
Индекс
<input className="Index" type="text" onChange={this.handleIndexChange} value={this.props.student.index}/>
Насока
<input className="Class" type="text" onChange={this.handleClassChange} value={this.props.student.class}/>
<input className="submit btn" type="submit" value="Промени"/>
</form>
</div>
);
}
}
export default EditStudentDetails;
I try to set initial value by setting each input's value to the appropriate prop. Then when something is changed in the input component state should update. But as I said, the value of each input does not change.
e.target.valuedirectly in the callback, it does not run right away. Its a better practice to pull it out first as you initially had it. You could also doe.persist();.