Following is my code to edit a form. This form is getting a bookDetails Object as props. I am storing the bookDetails that i get in props in a state variable bookDetailsObj. Now, this is working fine and even when I refresh the page the code does not break. But, when I click submit button, i’m getting the error “TypeError: Cannot read property ‘bookDetails’ of undefined”.
Another doubt is, even when I’m refreshing the page, the bookDetails data that im getting from props persists. That is, it is not undefined and I’m only setting the data in “componentDidMount”. I never need to get the data from local storage. What is the reason for that?
import {withRouter} from 'react-router-dom';
import LibNavbar from "./LibNavbar";
import swal from "sweetalert";
class EditBook extends Component{
constructor(props) {
super(props);
this.state={
// bookDetailsObj:[],
bookDetailsObj:this.props.location.state.bookDetails,
bookTitle: "",
publisher: "",
isbn: "",
language: "",
pages: 0,
authors: [""],
copies: 0,
isReferenceOnly : 0,
price: 0,
purchaseDate:"1/1/1111",
publicationYear : 0
}
this.handleChange = this.handleChange.bind(this)
this.handleChangeArray = this.handleChangeArray.bind(this)
this.fillForm=this.fillForm.bind(this)
this.submitChanges=this.submitChanges.bind(this)
}
submitChanges(e){
e.stopPropagation()
e.preventDefault()
swal("Submit Changes?","Once you submit older details cannot be revived","warning")
}
componentDidMount() {
if(this.props.location.state===undefined)
{
console.log("getting item....",localStorage.getItem("bookDetailsObj"))
this.setState({
bookDetailsObj:localStorage.getItem("bookDetailsObj")
}).then(()=>this.fillForm())
}
else
{
console.log("setting item....:" ,this.props.location.state.bookDetails)
localStorage.setItem("bookDetailsObj",this.props.location.state.bookDetails)
this.fillForm()
}
// console.log(this.state.bookDetailsObj)
}
fillForm(){
console.log(this.state.bookDetailsObj)
this.setState({
bookTitle: this.state.bookDetailsObj["bookTitle"],
publisher: this.state.bookDetailsObj["publisher"],
isbn: this.state.bookDetailsObj["isbnNumber"],
language: this.state.bookDetailsObj["language"],
pages: this.state.bookDetailsObj["noOfPages"],
authors: this.state.bookDetailsObj["authors"],
copies: this.state.bookDetailsObj["copies"],
isReferenceOnly : this.state.bookDetailsObj["isReferenceOnly"],
price: this.state.bookDetailsObj["price"],
purchaseDate: this.state.bookDetailsObj["purchaseDate"],
publicationYear : this.state.bookDetailsObj["publicationYear"]
})
}
handleChange(event) {
console.log("Handle change called")
const {name, value} = event.target;
this.setState({
[name]: value
})
console.log(this.state)
}
handleChangeArray(i, event) {
let authors = [...this.state.authors];
authors[i] = event.target.value;
this.setState({ authors });
}
createUI(){
return this.state.authors.map((el, i) =>
<div key={i} className={"addBookContainer"}>
<input type="text" className="form-control authorName" value={el||''} onChange={this.handleChangeArray.bind(this, i)} />
<input type='button' className="removeAuth" value='remove' onClick={this.removeClick.bind(this, i)}/>
<p></p>
</div>
)
}
addClick(){
this.setState(prevState => ({ authors: [...prevState.authors, '']}))
}
removeClick(i){
let authors = [...this.state.authors];
authors.splice(i,1);
this.setState({ authors });
}
render() {
return (
<div>
<LibNavbar/>
<head>
<link rel="stylesheet" href="https://bootswatch.com/4/flatly/bootstrap.min.css"/>
<link rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"
integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
crossOrigin="anonymous"/>
<title>Add Books</title>
</head>
<body>
<div className="container mt-4">
<h1 className="display-4 text-center"><i className="fas fa-book-open text-primary"></i> <span
className="text-secondary">Edit</span> Books</h1>
<form id="register-book-form">
<div className="register-book">
<label htmlFor="title">Book Title</label>
<input type="text" id="bookTitle" name = "bookTitle" className="form-control" required="true" value={this.state.bookTitle} onChange={this.handleChange} />
</div>
<div className="register-book">
<label htmlFor="author">Publisher</label>
<input type="text" id="publisher" name="publisher" className="form-control " required="true" value={this.state.publisher} onChange={this.handleChange}/>
</div>
<br/>
<div className="register-book-set4">
<label htmlFor="title">ISBN#</label>
<label htmlFor="price">Price</label>
<input type="text" id="isbn" name="isbn" className="form-control addIsbn" required="true" value={this.state.isbn} onChange={this.handleChange}/>
<input type="number" id="price" name="price" className="form-control addPrice" required="true" value={this.state.price} onChange={this.handleChange}/>
</div>
<br/>
<div className="register-book-set">
<label htmlFor="title">Language</label>
<label htmlFor="title">Number of Pages</label>
<input type="text" id="language" name="language" className="form-control addIsbn" required="true" value={this.state.language} onChange={this.handleChange}/>
<input type="number" id="pages" name="pages" className="form-control addPages" required="true" value={this.state.pages} onChange={this.handleChange}/>
</div>
<br/>
<div className="register-book-set2">
<label htmlFor="Number of Copies">Number of Copies</label>
<label htmlFor="Reference only">Is Reference Only</label>
<input type="number" id="copies" name = "copies" className="form-control addCopies" required="true" value={this.state.copies} onChange={this.handleChange} />
<input type="number" id="isReferenceOnly" name = "isReferenceOnly" className="form-control addReference" min="0" max="1" required="true" value={this.state.isReferenceOnly} onChange={this.handleChange} />
</div>
<br/>
<div className="register-book-set3">
<label htmlFor="purchaseDate">Date of Purchase</label>
<label htmlFor="publicationYear">Year of Publication</label>
<input type="date" id="purchaseDate" name="purchaseDate" className="form-control addPurchase" required="true" value={this.state.purchaseDate} onChange={this.handleChange}/>
<input type="number" id="publicationYear" name="publicationYear" className="form-control addPublication" required="true" min="1000" max="9999" value={this.state.publicationYear} onChange={this.handleChange}/>
</div>
<div className="register-book">
<br/>
<label htmlFor="title">Authors</label>
{this.createUI()}
<input type='button' value='Add more authors' onClick={this.addClick.bind(this)}/>
{/*<input type="submit" value="Submit" />*/}
</div>
<br/>
<div className="register-book mb-3">
<button type="submit" className="btn btn-primary btn-block" onSubmit={()=>this.submitChanges()}> Save</button>
</div>
<div className="register-book">
<button type="submit" className="btn btn-primary btn-block"> Reset</button>
</div>
<br/><br/>
</form>
</div>
</body>
</div>
);
}
}
export default withRouter(EditBook)