Are there any specific guidelines when passing callbacks as props to child components in React?
At some point my code ina app.js looks the following:
test() {
}
render(){
return (
<div className="App">
<MiniDrawer handleProductChange={this.handleProductChange.bind(this)} product={{icon:'', name:'Magnifier', height:'20px'}}/>
<div className='inrow'>
<PowerbiEmbedded
id={this.state.ReportId}
embedUrl={"https://app.powerbi.com/reportEmbed?reportId="+this.state.ReportId+"&groupId="+this.state.workspaceId}
accessToken={this.state.accesstoken}
filterPaneEnabled={true}
navContentPaneEnabled={true}
bookmarksPaneEnabled={true}
test={() => this.test}
//pageName={`${YOUR_PAGE_ID}`}
//embedType={`Report`}
tokenType={0}
width='100%'
height='1000px'
/>
</div>
</div>
);}
The MiniDrawer component does not signal any issues with handleProductChange callback. While simple callback which I am trying to pass to PowerBiEmbedded component fails with error:
DataCloneError: Failed to execute 'postMessage' on 'Window': () => this.test could not be cloned. I managed to extract the source of the problem. There is a function inside the child component using props with Object.assign. If i comment out this function error disappears. What can I do about it?
updateState (props) {
const nextState = Object.assign({}, this.state, props, {
pageName: this.props.pageName,
settings: {
/* panes:{
bookmarks: {visible: this.props.bookmarkPaneEnabled},
filters: {visible: this.props.filterPaneEnabled},
pageNavigation: {visible: this.props.navContentPaneEnabled}
},*/
filterPaneEnabled: this.props.filterPaneEnabled,
navContentPaneEnabled: this.props.navContentPaneEnabled,
bookmarkPaneEnabled: this.props.bookmarkPaneEnabled,
layoutType: this.props.mobile ? pbi.models.LayoutType.MobilePortrait : undefined
},
type: this.props.embedType ? this.props.embedType : 'report'
})
Any ideas what am I missing in here?
Ok. Found the solution. Object assign method for some reason fails to copy react callback '[native code]' issue. I'll let the purist to debate on that. I do not need the callback in this new object as it is passed further, and it is intended to have other properties, I simply clone the props myself with function removed ("zonk") in the example. Obviously this could be extended to verify the typeof key to make it more generic.
updateState (props) {
var distilledProps = _objectWithoutProperties(props, ['zonk'])
console.log(distilledProps)
const nextState = Object.assign({}, this.state, distilledProps, {
pageName: this.props.pageName,
settings: {
/* panes:{
bookmarks: {visible: this.props.bookmarkPaneEnabled},
filters: {visible: this.props.filterPaneEnabled},
pageNavigation: {visible: this.props.navContentPaneEnabled}
},*/
filterPaneEnabled: this.props.filterPaneEnabled,
navContentPaneEnabled: this.props.navContentPaneEnabled,
bookmarkPaneEnabled: this.props.bookmarkPaneEnabled,
layoutType: this.props.mobile ? pbi.models.LayoutType.MobilePortrait : undefined
},
type: this.props.embedType ? this.props.embedType : 'report'
})
... and helper function:
function _objectWithoutProperties(obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
}