我的应用程序有2个组件。当我将道具从父级传递给子级时,我使用map迭代道具并返回todoItemListjs组件中的列表但是它给出了错误
必须返回有效的React元素(或null)。您可能已经返回了undefined,数组或其他一些无效对象。
以下是我的组件
TodoList的
var React=require('react');
import TodoListItem from './TodoListItem.js';
var TodoList = React.createClass({
Remove: function(e){
this.props.onDelete(e);
},
DragStart: function(e){
this.dragged = e.currentTarget;
e.dataTransfer.effectAllowed = 'move';
},
DragEnd: function(e){
this.dragged.style.display="";
var IshasNode = false
Array.prototype.forEach.call (this.dragged.parentNode.childNodes, function (node) {
if(node.className=="placeholder")
IshasNode = true;
} );
if(!IshasNode)
return;
this.dragged.parentNode.removeChild(placeholder);
var data = this.props.items;
var from = Number(this.dragged.dataset.id);
var to = Number(this.over.dataset.id);
if(from < to) to--;
if(this.nodePlacement == "after") to++;
data.splice(to, 0, data.splice(from, 1)[0]);
this.setState({data: data});
},
DragOver: function(e) {
e.preventDefault();
this.dragged.style.display = "none";
if(e.target.className == "placeholder") return;
this.over = e.target;
var relY = e.clientY - this.over.offsetTop;
var height = this.over.offsetHeight / 2;
var parent = e.target.parentNode;
if(relY > height) {
this.nodePlacement = "after";
parent.insertBefore(placeholder, e.target.nextElementSibling);
}
else if(relY < height) {
this.nodePlacement = "before"
parent.insertBefore(placeholder, e.target);
}
},
render: function() {
var createItem = function(itemText,i) {
return (
<TodoListItem key={i} value={i} onDragEnd={this.DragEnd}
onDragStart={this.DragStart} onRemove = {this.Remove} AllItems={itemText}>{itemText}</TodoListItem>
);
};
var allitems = this.props.items;
// Here is the filter function
var status = this.props.filter[0].Status;
switch (status){
case 'false':
allitems = allitems.filter(t => !t.isDone)
break;
case 'true':
allitems = allitems.filter(t => t.isDone)
};
// Here is the search function
var queryText = this.props.filter[0].keyword;
if(queryText){
var queryResult=[];
allitems.forEach(function(item){
if(item.item.toLowerCase().indexOf(queryText)!=-1)
queryResult.push(item);
});
return <ul onDragOver={this.DragOver}>{queryResult.map(createItem,this)}</ul>;
}
return <ul onDragOver={this.DragOver}>{allitems.map(createItem,this)}</ul> ;
}
});
export default TodoList;
TodoListItem
var React=require('react');
var TodoListItem = React.createClass({
getInitialState : function(){
return {items:[{item:'',isDone:false,cost:0}]};
},
componentDidMount: function() {
},
ChangeHandler: function(e){
this.setState({
value: e.target.checked
});
this.props.children.isDone = e.target.checked;
},
RemoveHandler: function(){
this.props.onRemove(this.props.value);
},
DragEndHandler : function(e){
this.props.onDragEnd(e);
},
DragStartHandler : function(e){
this.props.onDragStart(e);
},
render: function(){
var _style = "line-through";
var space=" ";
if(!this.props.children.isDone)
_style ="none";
this.props.AllItems.items.map(function(todo)
{
console.log(todo.cost)
return (
<li data-id={this.props.value}
key={this.props.value} draggable="true" onDragEnd={this.DragEndHandler}
onDragStart={this.DragStartHandler}><button type="button" className="close pull-right" aria-hidden="true" onClick={this.RemoveHandler}>×</button><input type="checkbox" onChange={this.ChangeHandler} defaultChecked={this.props.children.isDone} /><span style={{"textDecoration": _style}}>{todo.item}{todo.cost}</span></li>
);
},this)
}
});
export default TodoListItem;
我也尝试将代码包装在div标签中,但它不起作用
Pease指南
答案 0 :(得分:3)
因为您没有从TodoListItem组件返回任何内容,请检查render方法。
将地图部分放在div中,如下所示:
return(
<div>
{
this.props.AllItems.items.map(function(todo){
....
}
}
</div>
)
或者将地图结果存储在变量中并返回最终结果,如下所示:
render(){
let data = this.props.AllItems.items.map(function(todo){
....
}
return(
<div> {data} </div>
);
}
正如comment中@ivarni所建议的那样:<li>
元素应该放在<ul>
内,div
是不允许的,所以根据以下内容更改结构我刚刚提供了错误的原因。
<强> Reference. 强>
答案 1 :(得分:1)
在TodoListItem渲染函数中没有返回任何内容。您的返回来自地图回调。将所有内容包装在一个div中并将其返回。
return (<div>
{this.props.AllItems.items.map(function(todo)
{
console.log(todo.cost)
return (
<li data-id={this.props.value}
key={this.props.value} draggable="true" onDragEnd={this.DragEndHandler}
onDragStart={this.DragStartHandler}><button type="button" className="close pull-right" aria-hidden="true" onClick={this.RemoveHandler}>×</button><input type="checkbox" onChange={this.ChangeHandler} defaultChecked={this.props.children.isDone} /><span style={{"textDecoration": _style}}>{todo.item}{todo.cost}</span></li>
);
},this);}
</div>)