setState() 不更新视图 - reactjs

setState() not updating the View - reactjs

大家好,

我刚开始在一个项目中使用 Reactjs,但遇到了这个问题,需要一些帮助。我正在尝试实现一个订单管理系统,其中使用 websockets 将订单推送到浏览器,然后将 reactjs 视图更新为该数据的一部分。在应该更新订单状态的交互过程中,UI 上处理了相关事件。因为我刚开始使用 Reactjs,所以我决定对我的数据集进行硬编码,这样我就可以看到列表中显示的订单。但是我无法单击列表并获取该单击项目的详细信息以刷新视图并显示在其分配的 space 上,当应用程序启动时仅显示订单列表没有详细视图,如代码所示低于或来自 http://jsfiddle.net/d5wvtyf0/。所以问题是我如何更新视图并显示通过调用 setState() 进行的更新,或者问题是我在已有的代码中做错了什么?

/*This is a container for the title on the lefthand side - In Progress/Ready etc*/
var OrderItemsTitle = React.createClass({
    render: function(){
        return(
            <p className="row-progress">{this.props.title_text}</p>
        );
    }
});

OrderItemButtons = React.createClass({
    render: function(){
        return(
            <a href="javascript:void(0)" className="row-order " onClick={this.props.handleClick}>
                <img src={this.props.orderitem.image_url} />
                <span className="txt">{this.props.orderitem.cust_name}</span>
                <span className="status">{this.props.orderitem.time}</span>
            </a>
        );
    }
});

/*This is the component that loads the items on the leftside of the screen*/
var ListViewOrderItemsContainer = React.createClass({
    handleClick: function(orderitem){
        this.props.onUserInput(orderitem);
        console.log(this.props.selectedorderitem);
    },
    render: function(){
        var filteredNewOrderItem = this.props.orderitems.filter(function(orderitem){
            return orderitem.status.toLowerCase().search('new') !== -1;
        });
        var filteredReadyOrderItem = this.props.orderitems.filter(function(orderitem){
            return orderitem.status.toLowerCase().search('ready') !== -1;
        });
        var filteredInProgressOrderItem = this.props.orderitems.filter(function(orderitem){
            return orderitem.status.toLowerCase().search('in_progress') !== -1;
        });


        return(
            <div className='leftContainer'>
                <OrderItemsTitle title_text='New' />
                <div className='new_progress_container'>
                    {
                        filteredNewOrderItem.map(function(orderitem, i){
                            return <OrderItemButtons key={i} handleClick={this.handleClick.bind(this,
                                orderitem)} orderitem={orderitem} selectedorderitem={this.props.selectedorderitem} />
                        }, this)
                    }
                </div>    
                <OrderItemsTitle title_text='In Progress' />
                <div className='in_progress_container'>
                    {
                        filteredInProgressOrderItem.map(function(orderitem, i){
                            return <OrderItemButtons key={i} handleClick={this.handleClick.bind(this, 
                                orderitem)} orderitem={orderitem}/>
                        }, this)
                    }
                </div>
                <OrderItemsTitle title_text='Ready' />
                <div className='ready_container'>
                    {
                        filteredReadyOrderItem.map(function(orderitem, i){
                            return <OrderItemButtons key={i} handleClick={this.handleClick.bind(this, 
                                orderitem)} orderitem={orderitem}/>
                        }, this)
                    }
                </div>    
            </div> 
        );
    }
});

/*This is the productline details that is shown on the righthand side of the OMS*/
var ProductItemLineDetails = React.createClass({
    render: function(){
        return (
            <p>                
                <span className="pull-right">
                    <strong>{this.props.productItem.productItemPrice}</strong>
                </span>
                <span className="text-muted">
                    <strong>{this.props.productItem.productItemName}</strong>
                </span>
            </p>
        );
    }
});

/*This is the container element for ProductItemLineDetails above*/
var ProductItemDetails = React.createClass({
    render: function(){
        console.log("this.props.orderitem.length = ", this.props.orderitem.length);
        var productRow;
        if (this.props.orderitem.length === 0){
            productRow = "";            
        }
        else {
            productRow = this.props.orderitem.products.map(function(product, i){
                return <ProductItemLineDetails key={i} productItem={product} />             
            });
            console.log("productRow = ", productRow);
        }

        return ( 
            <div>
                <div className="media">
                    <small className="pull-right">
                        23h ago
                    </small>
                    <div className="media-body">
                        <h4 className="media-heading">
                            Bruno Otas
                        </h4>
                        <span className="text-muted">
                            (234)-8087616915
                        </span> 
                        <br />
                        <span className="text-muted">
                            2 days ago at 2:30 am - 11.06.2014
                        </span>
                    </div>
                </div> 
                    <hr />            
                    {productRow}
                    <hr />
            </div>
        );
    }
});

/**This is the main container that houses everything on the right hand side of the view**/
var DetailViewOrderItemsContainers = React.createClass({
    render: function() {        
        return (
            <div className="rightContainer">
                <ProductItemDetails orderitem={this.props.selectedorderitem} />
            </div>    
        );
    }
});

var ParentContainer = React.createClass({
    getInitialState: function(){
        return {
            selectedorderitem: []
        }
    },
    handleUserInput: function(orderitem){
        this.setState({
          selectedorderitem: orderitem
        });
        console.log("setstate hit",  this.state.selectedorderitem);
        console.log("setstate order", orderitem);
      },
    render: function(){
        return (
            <div className="parentContainer">
                <ListViewOrderItemsContainer orderitems={this.props.orderitems} 
                onUserInput={this.handleUserInput} 
                selectedorderitem={this.state.selectedorderitem} />
                <DetailViewOrderItemsContainers selectedorderitem={this.state.selectedorderitem} />
            </div>
        );
    }
});


//var inProgressOrderDetails = [
var orderitems = [
{id: "2942934-343323-234242234-23423",status: 'new', time: "2", image_url: "/assets/images/profile_small.jpg", cust_name: "Nnamdi Jibunoh", products:[{id: "2422-34333-34343", variants: [{productItemPrice:"1800", productItemName: "Ice Cream"}]}] },
{id: "2942934-343323-234242234-23424",status: 'new', time: "3", image_url: "/assets/images/profile_small.jpg", cust_name: "Adeolu Adamu", products:[{id: "2422-34333-34343", variants: [{productItemPrice:"1800", productItemName: "Ice Cream"}]}] },
{id: "2942934-343323-234242234-23425",status: 'in_progress', time: "4", image_url: "/assets/images/profile_small.jpg", cust_name: "Alaku Ishienyi", products:[{id: "2422-34333-34343", variants: [{productItemPrice:"1800", productItemName: "Ice Cream"}]}] },
{id: "2942934-343323-234242234-23426",status: 'ready', time: "5", image_url: "/assets/images/profile_small.jpg", cust_name: "Ogochukwu Maduabum", products:[{id: "2422-34333-34343", variants: [{productItemPrice:"1800", productItemName: "Ice Cream"}]}] },
{id: "2942934-343323-234242234-23427",status: 'ready', time: "6", image_url: "/assets/images/profile_small.jpg", cust_name: "Bruno Otas", products:[{id: "2422-34333-34343", variants: [{productItemPrice:"1800", productItemName: "Ice Cream"}]}] },
];

React.render(<ParentContainer orderitems = {orderitems} />, document.getElementById('react_body'));

可能是因为您在实际更新之前记录状态:

handleUserInput: function(orderitem){
  this.setState({
    selectedorderitem: orderitem
  });
  console.log("setstate hit",  this.state.selectedorderitem);
  console.log("setstate order", orderitem);
}

应该是:

handleUserInput: function(orderitem){
  this.setState({
    selectedorderitem: orderitem
  }, function() {
    console.log("setstate hit",  this.state.selectedorderitem);
    console.log("setstate order", orderitem);
  })
}

setState 方法运行良好...您的代码和数据有问题。在这里,您的 Fiddle 已修复。

https://jsfiddle.net/69z2wepo/8311/

您在 ProductItemDetails 中的渲染函数正在检查对象中的长度 == 0。尽管您在 ParentContainer 中将 selectedorderitem 定义为一个数组,但是当您更新状态时,您正在传递一个特定对象(并且您的产品详细信息需要一个数组)。另外,您的 ProductItemLineDetails 中也发生了类似的事情(并且数据集在价格和产品名称方面完全相同,因此我对其进行了一些更改,以便您可以看到它有效)。