问题
Here is the codesandbox for this question: https://codesandbox.io/s/rdg-grouping-81b1s
I am using React-Data-Grid
to render a table. I render a ReactDataGrid
with two columns, and When you click on the text GROUP
in a header cell you group by that column.
To be able to have a custom header cell with that text GROUP
, I use the property headerRenderer
in the object defining the columns.
The value passed to this property is a function that takes an onClick
handler as parameter, and returns a functional React component that uses that onClick
handler.
The onClick
parameter is just a method on the original React component, and it is bound in the component's constructor.
As you can see, I am using this headerRenderer
property twice, once for each column. However, for the first column, I bind the parameter function to the React component again. For the second column I do not, and this generates an error when I try to click the GROUP
text for this column. See error image further below.
My question is: why do I have to bind given that I've already bound the function in the constructor?
import React from 'react';
import './App.css';
import ReactDataGrid from 'react-data-grid';
import { Data } from 'react-data-grid-addons';
const HeaderRowRenderer = function(props) {
return (
<div
style={{
backgroundColor: 'red',
paddingLeft: 10,
height: '100%',
padding: 0,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<span>{props.column.name}</span>
<span onClick={props.onClick}>GROUP</span>
</div>
);
};
const HeaderRenderer = function(groupBy, onClick) {
return function(props) {
return (
<HeaderRowRenderer
{...props}
onClick={function() {
onClick(groupBy);
}}
/>
);
};
};
const rows = [{ productname: 'Beef', quantity: 5 }, { productname: 'Veggies', quantity: 10 }];
class App extends React.Component {
columns = [
{
key: 'productname',
name: 'Product',
width: 200,
headerRenderer: HeaderRenderer('productname', this.groupBy.bind(this)),
},
{
key: 'quantity',
name: 'Quantity',
headerRenderer: HeaderRenderer('quantity', this.groupBy),
},
];
constructor(props) {
super(props);
this.state = {
groupBy: new Set([]),
};
this.groupBy = this.groupBy.bind(this);
}
groupBy(group) {
const newSet = new Set(this.state.groupBy);
if (newSet.has(group)) {
newSet.delete(group);
} else {
newSet.add(group);
}
this.setState({ groupBy: newSet });
}
render() {
const groupBy = Array.from(this.state.groupBy);
// const rows = this.props.orderItems;
const groupedRows = Data.Selectors.getRows({
rows: rows,
groupBy,
});
return (
<div>
<ReactDataGrid
columns={this.columns}
rowGetter={i => groupedRows[i]}
rowsCount={groupedRows.length}
minHeight={650}
/>
</div>
);
}
}
export default App;
I looked at the code for React-Data-Grid
, and I believe that the headerRenderer
prop is called as below:
getCell() {
const { height, column, rowType } = this.props;
const renderer = this.props.renderer || SimpleCellRenderer;
if (isElement(renderer)) {
// if it is a string, it's an HTML element, and column is not a valid property, so only pass height
if (typeof renderer.type === 'string') {
return React.cloneElement(renderer, { height });
}
return React.cloneElement(renderer, { column, height });
}
return React.createElement(renderer, { column, rowType });
}
I'm not very familiar with the ways in which a function that was bound using bind
and then is passed around can lose this boundedness. Does this happen as a result of React.cloneElement, or what could be the cause of it?
来源:https://stackoverflow.com/questions/56978862/how-can-a-react-method-bound-in-constructor-lose-its-boundedness-when-passed-as