[英]reactjs - Uncaught TypeError: Cannot read property 'map' of undefined
I'm trying to use the contents of a json return to not only populate my list, but when creating a new list to allow the selection of a parent. 我试图使用json return的内容不仅填充我的列表,而且在创建新列表以允许选择父对象时使用。
I have the list coming up in my Navigation but when I click on "Create New List" it gives the following error: 我的导航中有该列表,但是当我单击“创建新列表”时,出现以下错误:
Uncaught TypeError: Cannot read property 'map' of undefined
Which occurs on this particular part of code: 这发生在代码的这一特定部分:
render: function() {
var navNodes = this.props.data.map(function(nav) {
return (
React.createElement(NavItems, {name: nav.name, key: nav.id})
);
});
return (
React.createElement(Input, {
label: "Parent List",
ref: "input",
value: this.state.value,
bsStyle: this.state.validationState,
hasFeedback: true,
help: this.state.hint,
onChange: this.handleChange,
type: "select"},
this.renderPlaceholder(),
navNodes
)
);
Code: 码:
var Bootstrap = ReactBootstrap;
var Input = ReactBootstrap.Input;
var NavItems = React.createClass({
render: function() {
return (
<option value={1}>{navNodes}</option>
);
}
});
var NavItem = React.createClass({
render: function() {
return (
<li><a href="#">{this.props.name}</a></li>
);
}
});
var NavList = React.createClass({
render: function() {
var navNodes = this.props.data.map(function(nav) {
return (
<NavItem name={nav.name} key={nav.id}></NavItem>
);
});
return (
<ul className="nav">
<li className="current"><a href="#"><i className="glyphicon glyphicon-home"></i> Lists</a></li>
{navNodes}
</ul>
);
}
});
var NewListButton = React.createClass({
render: function() {
return (
<a {...this.props}
href="javascript:;"
role="button"
className={(this.props.className || '') + ' btn'}
/>
);
}
});
var ListNameInput = React.createClass({
getInitialState: function() {
return {
value: '',
hint: null,
validationState: null
};
},
handleChange: function() {
var newValue = this.refs.input.getValue(),
hint = null,
validationState = null,
length = newValue.length;
if (length > 2) {
validationState = 'success';
} else {
validationState = 'error';
if (length) {
hint = 'The name must be at least 3 characters long.';
} else {
hint = 'This value is required.';
}
}
this.setState({
value: newValue,
hint: hint,
validationState: validationState
});
},
isValid: function() {
return ('success' === this.state.validationState);
},
render: function() {
return (
<Input
label='Name'
ref='input'
value={this.state.value}
placeholder='Enter List Name'
bsStyle={this.state.validationState}
hasFeedback
help={this.state.hint}
onChange={this.handleChange}
type='text' />
);
}
});
var ListDescriptionInput = React.createClass({
getInitialState: function() {
return {
value: '',
hint: null,
validationState: null
};
},
handleChange: function() {
var newValue = this.refs.input.getValue(),
hint = null,
validationState = null,
length = newValue.length;
if (length > 2) {
validationState = 'success';
} else {
validationState = 'error';
if (length) {
hint = 'The description must be at least 3 characters long.';
} else {
hint = 'This value is required.';
}
}
this.setState({
value: newValue,
hint: hint,
validationState: validationState
});
},
isValid: function() {
return ('success' === this.state.validationState);
},
render: function() {
return (
<Input
label='Description'
ref='input'
value={this.state.value}
placeholder='Enter Description'
bsStyle={this.state.validationState}
hasFeedback
help={this.state.hint}
onChange={this.handleChange}
type='text' />
);
}
});
var WidgetListSelect = React.createClass({
getInitialState: function() {
return {
value: 0,
hint: null,
validationState: null
};
},
handleChange: function() {
var newValue = Number(this.refs.input.getValue()),
hint = null,
validationState = null;
if (0 === newValue) {
validationState = 'error';
hint = 'You must select an parent list.';
} else {
validationState = 'success';
}
this.setState({
value: newValue,
hint: hint,
validationState: validationState
});
},
isValid: function() {
return ('success' === this.state.validationState);
},
renderPlaceholder: function() {
if (0 !== this.state.value)
return null;
// Show placeholder only prior to a value being selected
return (
<option value={0}>
Please select a Parent List
</option>
);
},
render: function() {
var navNodes = this.props.data.map(function(nav) {
return (
<NavItems name={nav.name} key={nav.id}></NavItems>
);
});
return (
<Input
label='Parent List'
ref='input'
value={this.state.value}
bsStyle={this.state.validationState}
hasFeedback
help={this.state.hint}
onChange={this.handleChange}
type='select'>
{this.renderPlaceholder()}
{navNodes}
</Input>
);
}
});
var CreateNewListForm = React.createClass({
handleSubmit: function() {
var isValid =
!!(this.refs.nameInput.isValid()
& this.refs.descriptionInput.isValid()
& this.refs.widgetlistSelect.isValid());
if (isValid) {
this.props.closeModal();
} else {
// Force validation of each element to show errors to user
this.refs.nameInput.handleChange();
this.refs.descriptionInput.handleChange();
this.refs.widgetlistSelect.handleChange();
}
},
render: function() {
return (
<div>
<ListNameInput
ref='nameInput' />
<ListDescriptionInput
ref='descriptionInput' />
<WidgetListSelect
ref='widgetlistSelect' />
<Bootstrap.ButtonToolbar>
<Bootstrap.Button
onClick={this.handleSubmit}>
Save
</Bootstrap.Button>
<Bootstrap.Button
onClick={this.props.closeModal}>
Cancel
</Bootstrap.Button>
</Bootstrap.ButtonToolbar>
</div>
);
}
});
var NavBox= React.createClass({
loadNavsFromServer: function() {
$.ajax({
url: "http://servername/api/widgetlists/?format=json",
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error("http://servername/api/widgetlists/?format=json", status, err.toString());
}.bind(this)
});
},
handleListSubmit: function(comment) {
// TODO: submit to the server and refresh the list
},
getInitialState: function() {
return {
modalVisible: false,
data: []};
},
onClick: function() {
this.setState({modalVisible: true});
},
hideModal: function() {
this.setState({modalVisible: false});
},
renderModal: function() {
return (
<Bootstrap.Modal
show={this.state.modalVisible}
onHide={this.hideModal}>
<Bootstrap.Modal.Body>
<CreateNewListForm
closeModal={this.hideModal} />
</Bootstrap.Modal.Body>
</Bootstrap.Modal>
);
},
componentDidMount: function() {
this.loadNavsFromServer();
},
render: function() {
return (
<div className="col-md-2">
<div className="sidebar content-box" style={{display: "block"}}>
<NavList data={this.state.data} />
{this.renderModal()}
<Bootstrap.Button onClick={this.onClick}>
Create New List
</Bootstrap.Button>
</div>
</div>
);
}
});
module.exports = {
NavBox: NavBox
}
You need a return value in getDefaultProps
. 您需要在
getDefaultProps
返回一个值。
https://facebook.github.io/react/docs/reusable-components.html#default-prop-values https://facebook.github.io/react/docs/reusable-components.html#default-prop-values
getDefaultProps: function() {
return {
data: []
};
}
Also, it's good practice to define your prop types too: 另外,也是定义道具类型的好习惯:
propTypes: {
data: React.PropTypes.array.isRequired
}
Whilst I'd avoid ES6/7 Class sugar as I'm not a fan of that specification (it's unhealthy for your JS mind like sugar), nevertheless, if you like it then their is also a way to define these as static
property defaultProps
. 虽然我会避免使用ES6 / 7类糖,因为我不喜欢该规范(但是像糖一样对您的JS头脑来说这是不健康的),但是,如果您喜欢它,那么它们也是将其定义为
static
属性defaultProps
一种方式。
class Foo extends React.Component {
static defaultProps = {
bar: React.PropTypes.array.isRequired
}
}
https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#es7-property-initializers https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#es7-property-initializers
this.props.data
is not defined the first time render()
is first called, and you are trying to call .map()
on undefined, which results in an error. 首次调用
render()
时未定义this.props.data
,并且您尝试在undefined上调用.map()
,这会导致错误。
You should check that data is defined before calling map on it, and otherwise set navNodes to an empty array. 您应在调用map之前检查数据是否已定义,否则应将navNodes设置为空数组。
const data = this.props.data;
const navNodes = data ? data.map(...your function...) : [];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.