我想使用json返回的內容不僅填充我的列表,而且創建一個新的列表以允許選擇一個父項。reactjs - 未捕獲TypeError:無法讀取未定義的屬性'地圖'
我名單即將在我的導航,但是當我點擊「創建新的列表」它提供了以下錯誤:
Uncaught TypeError: Cannot read property 'map' of undefined
其中關於這段代碼特定部分發生:
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
)
);
代碼:
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
}
所以'this.props.data'顯然不是一個數組,你有沒有嘗試登錄它,看看它到底是什麼 – adeneo
嘗試登錄了'render'調用,它可能是在道具準備好之前多次調用'this.props.data'可能是不確定的,這會導致這個錯誤。我還推薦使用[lodash](http://lodash.com)的'_.map',這是類型安全的。 –