map函数不会在reactjs中返回任何内容

时间:2017-07-19 12:01:03

标签: reactjs

我的应用程序有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}>&times;</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指南

2 个答案:

答案 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}>&times;</button><input type="checkbox" onChange={this.ChangeHandler} defaultChecked={this.props.children.isDone} /><span style={{"textDecoration": _style}}>{todo.item}{todo.cost}</span></li>
        );
    },this);}
</div>)