Reputation: 3933
I want to load all companies via AJAX request into a state
property when the user clicks on the select
box.
This is the code:
import React, { Component } from 'react';
import SelectOption from './SelectOption';
class CreateFreightEntryModal extends Component {
constructor(props) {
super(props);
this.state = {
freights: props.freights,
onClose: props.onClose,
onClick: props.onClick,
companies: [],
};
}
loadCompanies(event) {
$.ajax({
type: "POST",
context:this,
dataType: "json",
async: true,
url: "../data/get/json/companies",
data: ({
_token : window.Laravel.csrfToken,
}),
success: function (data) {
var arr = $.map(data, function(el) { return el; });
this.setState({
companies: arr
})
}
});
}
render() {
return (
<div className="modal fade" id="createFreightEntryModal" tabIndex="-1" role="dialog">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">New freight entry</h4>
</div>
<div className="modal-body">
<div>
<div>
<form onSubmit={this.add.bind(this)}>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<strong>Create a new freight entry:</strong>
</div>
</div>
<div className="row">
<div className="col-xs-4 col-sm-4 col-md-4 col-lg-4">
Company
</div>
<div className="col-xs-8 col-sm-8 col-md-8 col-lg-8">
<div className="form-group" onClick={this.loadCompanies.bind(this)}>
<select className="selectpicker show-tick form-control" data-live-search="true" data-title="Please select" ref="Firma" required>
{
this.state.companies.map((company)=> {
return (
<SelectOption value={company.Nummer} displayValue={company.Bezeichnung} key={company.id} />
);
})
}
</select>
</div>
</div>
</div>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div className="form-group">
<button type="submit" className="btn btn-success"><span className="glyphicon glyphicon-floppy-disk"></span> Save </button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
);
}
}
export default CreateFreightEntryModal
When I add the componentWillReceiveProps(nextProps)
method, I get this error.
This error occurs when the page is loaded and not when I click on the select box!
componentWillReceiveProps(nextProps) {
this.setState({
companies: nextProps.companies,
});
}
TypeError: this.state.companies is undefined
This is the part where the error occurs:
...
this.state.companies.map((company)=> {
...
How can I solve this issue?
Upvotes: 1
Views: 1966
Reputation: 36965
Using this construct:
componentWillReceiveProps(nextProps) {
this.setState({
companies: nextProps.companies,
});
}
you update state.companies
every time the component receives ANY props, even when there are no companies
in the props. And when the nextProps
don't have companies
it is set to undefined
.
Let's illustrate it this way:
{
let props = { freights : [ 'a', 'b', 'c' ] }
this.setState({ companies : props.companies })
/* state.companies are now undefined, because props.companies are undefined */
}
Fix:
componentWillReceiveProps(nextProps) {
if( nextProps.companies ){
this.setState({
companies: nextProps.companies,
});
}
}
BTW the problem with success callback scope I have mentioned in a comment may still apply.
Upvotes: 3