reactjs在map函数中更新父级状态

时间:2015-06-23 20:27:19

标签: javascript reactjs

我目前有两个组件LootBoxLootTableLootTableLootBox的孩子。

var LootBox = React.createClass({
            loadLootFromServer: function() {
                $.ajax({
                  url: this.props.url,
                  dataType: 'json',
                  cache: false,
                  success: function(data) {
                    this.setState({data: data});
                  }.bind(this),
                  error: function(xhr, status, err) {
                    console.error(this.props.url, status, err.toString());
                  }.bind(this)
                });
            },
            loadItemsFromServer: function() {
                $.ajax({
                  url: this.props.itemData,
                  dataType: 'json',
                  cache: false,
                  success: function(bossData) {
                    this.setState({bossData: bossData, loading: {"done": true}});
                  }.bind(this),
                  error: function(xhr, status, err) {
                    console.error(this.props.itemData, status, err.toString());
                  }.bind(this)
                });
            },
            handleClick: function(e, slot, item_id, item_bonus) {
                e.preventDefault();
                this.state.data.head.id = item_id;
                this.state.data.head.bonus = item_bonus;
                this.setState({data: this.state.data});
            },
            getInitialState: function() {
                return {
                    data: {
                        main_hand: {},
                        off_hand: {},
                        head: {},
                        neck: {},
                        shoulders: {},
                        back: {},
                        chest: {},
                        wrist: {},
                        hands: {},
                        waist: {},
                        legs: {},
                        feet: {},
                        finger1: {},
                        finger2: {},
                        trinket1: {},
                        trinket2: {}
                    },
                    bossData: {
                        main_hand: [],
                        off_hand: [],
                        head: [],
                        neck: [],
                        shoulders: [],
                        back: [],
                        chest: [],
                        wrist: [],
                        hands: [],
                        waist: [],
                        legs: [],
                        feet: [],
                        fingers: [],
                        trinkets: [],

                    },
                    loading: {"done": false}
                };
            },
            componentDidMount: function() {
                this.loadLootFromServer();
                this.loadItemsFromServer();
            },
            render: function () {
                if(this.state.loading.done == false){
                    return (<div id="spin"></div>)
                }
                else {
                    return (
                        <LootTable data={this.state.data} bossData={this.state.bossData} handleClick={this.handleClick} />
                    )
                }
            } 
        });

        var LootTable = React.createClass({
            render: function () {
                return (
                    <div className="table-responsive">
                        <table className="table table-bordered table-hover">
                            <tr>
                                <th>Head <a href="#" data-toggle="collapse" data-target="#items_head"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                                <th>Neck <a href="#" data-toggle="collapse" data-target="#items_neck"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                            </tr>
                            <tr>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.head.id, "&bonus=", this.props.data.head.bonus)}>{this.props.data.head.id}</a>
                                    <div id="items_head" className="collapse"><h4>Select Replacement Item</h4>

                                        {this.props.bossData.head.map(function(item, i, this.props.handleClick){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" onClick={this.props.handleClick.bind(null, 'head', item.id, item.bonus)} rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.neck.id, "&bonus=", this.props.data.neck.bonus)}>{this.props.data.neck.id}</a>
                                    <div id="items_neck" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.neck.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                            </tr>
                            <tr>
                                <th>Shoulders <a href="#" data-toggle="collapse" data-target="#items_shoulders"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                                <th>Chest <a href="#" data-toggle="collapse" data-target="#items_chest"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                            </tr>
                            <tr>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.shoulders.id, "&bonus=", this.props.data.shoulders.bonus)}>{this.props.data.shoulders.id}</a>
                                    <div id="items_shoulders" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.shoulders.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.chest.id, "&bonus=", this.props.data.chest.bonus)}>{this.props.data.chest.id}</a>
                                    <div id="items_chest" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.chest.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                            </tr>
                            <tr>
                                <th>Waist <a href="#" data-toggle="collapse" data-target="#items_waist"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                                <th>Legs <a href="#" data-toggle="collapse" data-target="#items_legs"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                            </tr>
                            <tr>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.waist.id, "&bonus=", this.props.data.waist.bonus)}>{this.props.data.waist.id}</a>
                                    <div id="items_waist" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.waist.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.legs.id, "&bonus=", this.props.data.legs.bonus)}>{this.props.data.legs.id}</a>
                                    <div id="items_legs" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.legs.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                            </tr>
                            <tr>
                                <th>Feet <a href="#" data-toggle="collapse" data-target="#items_feet"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                                <th>Wrist <a href="#" data-toggle="collapse" data-target="#items_wrist"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                            </tr>
                            <tr>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.feet.id, "&bonus=", this.props.data.feet.bonus)}>{this.props.data.feet.id}</a>
                                    <div id="items_feet" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.feet.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.wrist.id, "&bonus=", this.props.data.wrist.bonus)}>{this.props.data.wrist.id}</a>
                                    <div id="items_wrist" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.wrist.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                            </tr>
                            <tr>
                                <th>Hands <a href="#" data-toggle="collapse" data-target="#items_hands"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                                <th>Back <a href="#" data-toggle="collapse" data-target="#items_back"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                            </tr>
                            <tr>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.hands.id, "&bonus=", this.props.data.hands.bonus)}>{this.props.data.hands.id}</a>
                                    <div id="items_hands" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.hands.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.back.id, "&bonus=", this.props.data.back.bonus)}>{this.props.data.back.id}</a>
                                    <div id="items_back" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.back.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                            </tr>
                            <tr>
                                <th>Finger 1 <a href="#" data-toggle="collapse" data-target="#items_finger1"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                                <th>Finger 2 <a href="#" data-toggle="collapse" data-target="#items_finger2"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                            </tr>
                            <tr>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.finger1.id, "&bonus=", this.props.data.finger1.bonus)}>{this.props.data.finger1.id}</a>
                                    <div id="items_finger1" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.fingers.map(function(item){
                                        return (<div key={"item1_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.finger2.id, "&bonus=", this.props.data.finger2.bonus)}>{this.props.data.finger2.id}</a>
                                    <div id="items_finger2" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.fingers.map(function(item){
                                        return (<div key={"item2_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                            </tr>
                            <tr>
                                <th>Trinket 1 <a href="#" data-toggle="collapse" data-target="#items_trinket1"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                                <th>Trinket 2 <a href="#" data-toggle="collapse" data-target="#items_trinket2"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                            </tr>
                            <tr>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.trinket1.id, "&bonus=", this.props.data.trinket1.bonus)}>{this.props.data.trinket1.id}</a>
                                    <div id="items_trinket1" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.trinkets.map(function(item){
                                        return (<div key={"item1_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.trinket2.id, "&bonus=", this.props.data.trinket2.bonus)}>{this.props.data.trinket2.id}</a>
                                    <div id="items_trinket2" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.trinkets.map(function(item){
                                        return (<div key={"item2_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                            </tr>
                            <tr>
                                <th>Main Hand <a href="#" data-toggle="collapse" data-target="#items_main_hand"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                                <th>Off Hand <a href="#" data-toggle="collapse" data-target="#items_off_hand"><span className="glyphicon glyphicon-th-list pull-right"></span></a></th>
                            </tr>
                            <tr>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.main_hand.id, "&bonus=", this.props.data.main_hand.bonus)}>{this.props.data.main_hand.id}</a>
                                    <div id="items_main_hand" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.main_hand.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                                <td>
                                    <a href={"http://wowhead.com/item=".concat(this.props.data.off_hand.id, "&bonus=", this.props.data.off_hand.bonus)}>{this.props.data.off_hand.id}</a>
                                    <div id="items_off_hand" className="collapse"><h4>Select Replacement Item</h4>
                                        {this.props.bossData.off_hand.map(function(item){
                                        return (<div key={"item_"+item.id}>
                                            <a href="#" rel={"item=".concat(item.id, "&bonus=", item.bonus)}>{item.name}</a>
                                        </div>);
                                    })}</div>
                                </td>
                            </tr>
                        </table>
                    </div>
                )
            }
        });

        React.render(
            <LootBox url="/loot.json" itemData='/bosses.json' />,
            document.getElementById('content')
        );

基本上我想在这里实现的是在data中点击链接时更改LootTable的状态。

E.G每当用户点击{this.props.BossData.head.map(...地图中的链接时。我需要它来更新this.state.data.head.idthis.state.data.head.bonus

我几个小时以来一直在反对这个问题,尝试了各种解决方案,但都没有。

如果我尝试绑定this.props.handleClick它告诉我无法读取未定义的属性绑定。任何想法?

1 个答案:

答案 0 :(得分:2)

map函数内部的

this与map函数之外的this上下文不同。但是,您可以将{_ 1}}传递给您想要的上下文。

所以,尝试使你的地图功能像

map