以编程方式反应设置组件道具

问题描述 投票:2回答:2

我试图以某种方式动态地设置一个react(v15)组件的道具回调函数。像下面这样的东西,萌芽它不起作用,因为我想要它。

这背后的整个想法是弹出窗口需要返回特定在网格中按下的网格项的特定数据(html表)。

有关如何存档组件及其道具的动态设置的任何建议吗?

下面的代码给出了这个错误:

TypeError: can't define property "dynamicCallback": Object is not extensible

(我想元素道具是用Object.preventExtensions设置的)

getGridColumnData() {
    var notificationsColumnsObj = columns.GridData; // from json file, Array With columns

        for (let iColumn = 0; iColumn < notificationsColumnsObj.length; iColumn++) {
            if (notificationsColumnsObj[iColumn].field === 'Landlord_Name') {
                notificationsColumnsObj[iColumn]['editor'] = function (container, options) {

                    that.refs.searchCompanyPopup.props.dynamicCallback = function (data) {
                        var landlordName = null;
                        var landlordCode = null;
                        if (data) {
                            landlordCode = data.Code;
                            landlordName = data.Name;
                        }
                        options.model.set('Landlord_Code', landlordCode);
                        options.model.set('Landlord_Name', landlordCode);
                    };
                };
            }
        }
    return notificationsColumnsObj;
}
<SearchPopup ref="searchPopup" data={this.state.data} />

-

更新

我是如何设法将它最终工作的。我使用状态来设置弹出窗口用于回调的函数。当您单击网格中的项目时:callsColumnsObj [iColumn] ['editor']被调用,然后在完成调用该函数时为弹出回调设置状态。

var that;
class TheComponent extends React.Component {
    constructor(props,context) {
        super(props,context);
        this.state={
            data: {},
            landlordSelectedCallback: function (data) {},
        }
        that = this;
    }

    getGridColumnData() {
    var notificationsColumnsObj = columns.GridData; // from json file, Array With columns

        for (let iColumn = 0; iColumn < notificationsColumnsObj.length; iColumn++) {
            //only one item will match this, not multiple
            if (notificationsColumnsObj[iColumn].field === 'Landlord_Name') {
                notificationsColumnsObj[iColumn]['editor'] = function (container, options) {
                    that.setState({
                        landlordSelectedCallback: function (data) {
                            var landlordName = null;
                            var landlordCode = null;
                            if (data) {
                                landlordCode = data.Code;
                                landlordName = data.Name;
                            }
                            options.model.set('Landlord_Code', landlordCode);
                            options.model.set('Landlord_Name', landlordCode);
                        }
                    }, () => { //callback function, after the state is set
                        $(ReactDOM.findDOMNode(that.refs.searchPopup)).modal(); //shows the <SearchPopup modal

                        $(ReactDOM.findDOMNode(that.refs.searchPopup)).off('hide.bs.modal');
                        $(ReactDOM.findDOMNode(that.refs.searchPopup)).on('hide.bs.modal', function (e) {
                            $(ReactDOM.findDOMNode(that.refs.searchPopup)).off('hide.bs.modal');
                            that.closeGridCellFromEditing(); //closes the grid cell edit mode
                        });
                    });
                };
            }
        }
        return notificationsColumnsObj;
    }

    render() {
        return (<div>[other nodes]
                    <SearchPopup ref="searchPopup" data={this.state.data} onModalFinished={this.state.landlordSelectedCallback} />
                </div>);
    }
}
javascript reactjs
2个回答
2
投票

这有两个原因:

  1. 因为你的ref被称为searchPopup,而不是props。根据the documentation for legacy string refs,你可以通过this.refs.searchProps访问它。
  2. 因为props are read-only

第二条规则是积极执行的,我有点惊讶,但那是件好事。 :-)

如果要更改子组件的道具,可以通过更改状态来实现,以便使用新道具重新渲染子项。这是React的Lifting State Up / Data Flows Down哲学的一部分。


0
投票

而不是提供新的回调函数,只需保留一个函数,但向其提供数据。

getGridColumnData() {
    var notificationsColumnsObj = columns.GridData; //from json file, Array With columns

        for (let iColumn = 0; iColumn < notificationsColumnsObj.length; iColumn++) {
            if (notificationsColumnsObj[iColumn].field === 'Landlord_Name') {
                notificationsColumnsObj[iColumn]['editor'] = (function (container, options) {
                    this.options = options
                }).bind(this);
            }
        }
    return notificationsColumnsObj;
}

dynamicCallback = function (data) {
  var landlordName = null;
  var landlordCode = null;
  if (data) {
    landlordCode = data.Code;
    landlordName = data.Name;
  }
  this.options.model.set('Landlord_Code', landlordCode);
  this.options.model.set('Landlord_Name', landlordCode);
}

render() {
  return <SearchPopup ref="searchPopup" data={this.state.data} dynamicCallback = {this.dynamicCallback.bind(this)}/>
}
© www.soinside.com 2019 - 2024. All rights reserved.