繁体   English   中英

由于父级重新渲染,ReactJS计算组件道具更改时的状态

[英]ReactJS calculate state on change to components props as a result of parent re-render

我有一个用于学习ReactJS的示例应用程序。

它是一组嵌套的主要详细信息组件。 有一个城市列表,您单击一个城市,就会显示该城市的一些详细信息以及该城市的公交路线列表。 当您单击公交路线时,会显示该公交路线的某些(相当可悲的:)详细信息。

这是一个小提琴

数据全部包含在某些数组中,并且有两个数据帮助器函数,但这只是为了使其变得简单,稍后我将把数据移至AJAX调用。

如果您看小提琴,您会看到正确单击城市会更新城市详细信息和公交路线列表,然后正确单击公交路线会显示该公交路线的详细信息。 问题在于,单击其他城市确实会更新城市的公交路线,但不会显示该城市的第一条公交路线。

这是问题所在:我认为CityBusRoutes组件需要重新计算/更新其状态,但是我不知道如何/在何处执行此操作。 CityBusRoutes提供了一个cityid ,然后准备了一条路线列表,我认为应该更改其状态以将第一个路线存储为所选路线。 最初,逻辑位置似乎在render方法中,但这显然是错误的。

请随时提供有关改进设计等的任何建议或文档链接。谢谢。

这是代码:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style type="text/css"> li{ cursor: pointer; } </style>
</head>
<body>
    <div id="app"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/JSXTransformer.js"></script>
<script type="text/jsx">
var cityListing = [
    {id: 1, name: 'Rome', desc: 'Capital of Italy'}, 
    {id: 2, name: 'London', desc: 'Capital of UK'}, 
    {id: 3, name: 'Washington', desc: 'Capital of USA'}
];

var cityBuses = [
    {
        cityid: 1, 
        routes: [   
            {id: 707, desc: 'Rome to Beach'},
            {id: 717, desc: 'Beach to Rome'},
            {id: 708, desc: 'Rome to Naples'},
            {id: 718, desc: 'Naples to Rome'}
        ]
    },
    {
        cityid: 2,
        routes: [   
            {id: 801, desc: 'London to Beach'},
            {id: 811, desc: 'Beach to London'},
            {id: 802, desc: 'London to Manchester'},
            {id: 812, desc: 'Manchester to London'}
        ]
    },
    {
        cityid: 3,
        routes: [   
            {id: 901, desc: 'Washington to Beach'},
            {id: 911, desc: 'Beach to Washington'},
            {id: 902, desc: 'Washington to New York'},
            {id: 912, desc: 'New York to Washington'}
        ]
    }
];
function findCityBusRoutes(cityid){
    for(var i = 0; i < cityBuses.length; i++){
        if(cityBuses[i].cityid === cityid) return cityBuses[i];
    } 
    return null;
}
function findBusRouteDetails(routeid){
    var c, i, routes;
    if(typeof routeid !== 'number') routeid = parseInt(routeid);
    for(var c=0; c < cityBuses.length; c++){
        routes = cityBuses[c].routes;
        for(var i=0; i < routes.length; i++){
            if(routes[i].id === routeid){
                return "Take a scenic bus trip from " + routes[i].desc + '(' + routes[i].id + ')';
            }
        }
    }
    return null;
}
var CityList = React.createClass({
    selectCity: function(citylistitem){
        this.setState( {selectedCity: citylistitem} );
    },
    getInitialState: function(){
        return {selectedCity: cityListing[0]};
    }, 
    render: function(){

        var listItems = cityListing.map(function(item){
            return <CityListItem key={item.id} data={item} onClick={this.selectCity} />
        }, this);  

        return(
            <div>
                <ul>{listItems}</ul>
                <CityDetail data={this.state.selectedCity} />
            </div>
        );

    }
});

var CityListItem = React.createClass({
    clickItem: function(e){
        this.props.onClick(this.props.data);
    },
    render: function(){
        return (
            <li onClick={this.clickItem}>{this.props.data.name}</li>
        )
    }
});

var CityDetail = React.createClass({
    render: function(){
        return(
            <div>
                <h3>City of {this.props.data.name}</h3>
                <p>{this.props.data.desc}</p>
                <CityBusRoutes data={this.props.data} />
            </div>
        );  
    }
});

var CityBusRoutes = React.createClass({
    clickBusRoute: function(e){     
        this.setState({ routeid: e.currentTarget.getAttribute('data-routeid')});
    },
    getInitialState: function(){
        var cityRoutes = findCityBusRoutes(this.props.data.id);
        return {routeid: cityRoutes.routes[0].id};
    },
    render: function(){
        var cityRoutes = findCityBusRoutes(this.props.data.id);

        var routeItems = cityRoutes.routes.map(function(route){
            return (
                <li data-routeid={route.id} onClick={this.clickBusRoute} >Route: {route.id}, Description: {route.desc}</li>
            )
        }, this);


        return(
            <div>
                <h3>{this.props.data.name} City Bus Routes</h3>
                <ul>{routeItems}</ul>
                <CityBusRouteDetail routeid={this.state.routeid}/>
            </div>
        );

    }   
});

var CityBusRouteDetail = React.createClass({
    render: function(){
        var rd = findBusRouteDetails(this.props.routeid);

        return(
            <div>
                <h5>Route Details</h5>
                <p>{rd}</p>
            </div>
        );
    }
});

React.render(<CityList />, document.getElementById('app'));
</script>
</body>
</html>  

好的,所以我找到了CityBusRoutes向我的CityBusRoutes组件添加componentWillReceiveProps()方法是我想要的。 基本上在组件道具发生变化时为计算新状态提供了一个位置。

componentWillReceiveProps: function(nextProps){
    var cityRoutes = findCityBusRoutes(nextProps.data.id);
    this.setState({routeid: cityRoutes.routes[0].id});
}

继承关系的React Docs

这是工作的小提琴

仍然很高兴收到有关上述设计的任何评论

componentWillMount和componentWillReceiveProps是解决这些问题的好方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM