Javascript 构造函数中绑定的React方法如何丢失它';作为参数传递时的有界性?
以下是此问题的代码沙盒: 我正在使用Javascript 构造函数中绑定的React方法如何丢失它';作为参数传递时的有界性?,javascript,reactjs,react-data-grid,Javascript,Reactjs,React Data Grid,以下是此问题的代码沙盒: 我正在使用React数据网格呈现一个表。我呈现一个包含两列的ReactDataGrid,当您单击标题单元格中的文本GROUP时,您将按该列进行分组 为了能够使用带有该文本的自定义标题单元格组,我在定义列的对象中使用了属性headerRenderer 传递给此属性的值是一个函数,该函数将onClick处理程序作为参数,并返回使用该onClick处理程序的函数React组件 onClick参数只是原始React组件上的一个方法,它绑定在组件的构造函数中 如您所见,我将使用此
React数据网格
呈现一个表。我呈现一个包含两列的ReactDataGrid
,当您单击标题单元格中的文本GROUP
时,您将按该列进行分组
为了能够使用带有该文本的自定义标题单元格组
,我在定义列的对象中使用了属性headerRenderer
传递给此属性的值是一个函数,该函数将onClick
处理程序作为参数,并返回使用该onClick
处理程序的函数React组件
onClick
参数只是原始React组件上的一个方法,它绑定在组件的构造函数中
如您所见,我将使用此headerRenderer
属性两次,每列一次。但是,对于第一列,我再次将参数函数绑定到React组件。对于第二列,我没有这样做,当我尝试单击该列的组
文本时,会产生一个错误。请参阅下面的错误图像
我的问题是:既然我已经在构造函数中绑定了函数,为什么我必须绑定呢
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;
我不太熟悉使用bind
绑定然后传递的函数如何失去这种有界性。这是由于React.cloneElement导致的,还是可能的原因
在事件处理程序中使用箭头函数,而不是标准函数。因此,在插入
onClick={function(…){…}
时,它将具有“函数运行时的执行上下文是什么”,使用onClick={(…)=>{…}
,它将具有“声明函数时的执行上下文是什么”,例如,函数内部的这个
指向函数外部的东西。实际上,@Mike'Pomax'Kamermans我只是切换到常规函数,因为它不适用于箭头函数,我试图避免与“无论执行上下文是什么”相关的陷阱。如果您认为可以通过该更改使其正常工作,那么这里有一个codesandbox示例:首先,静态属性中的this
应该是什么?(查看您的列定义。也就是说,这肯定不是最小的:删除重复,让groupBy简单地设置任何状态值,渲染可以显示愚蠢的状态更改!
for等等。这里仍然有很多代码与您所问的问题无关。(mcve通常要求删除真实代码的所有外观,并纯粹深入到一件对您不起作用的事情)这是一个时间问题。当您定义这样的“静态”属性时,它会被转换/编译到构造函数中(正如在构造函数中定义的那样)。它不是真正的静态。但构造函数中的赋值可能是在您将函数绑定到类之前发生的。@JohnRuddell只是为了正确起见,这不是静态字段定义,而是类字段定义。正如您所说,这只是编写构造函数代码的语法糖分,因为这就是它的最终目的。您的建议但是很可能是正确的,尝试以这种方式绑定此
是不可靠的。请在事件处理程序中使用箭头函数,而不是标准函数。因此,在插入onClick={function(..){…}
时,将使用onClick={(…)=>{…}
,它将具有“声明函数时的执行上下文”,例如,函数内部的这个
指向函数外部的东西。实际上,@Mike'Pomax'Kamermans我只是切换到常规函数,因为它不适用于箭头函数,我试图避免与“无论执行上下文是什么”相关的陷阱。如果您认为可以通过该更改使其正常工作,那么这里有一个codesandbox示例:首先,静态属性中的this
应该是什么?(查看您的列定义。也就是说,这肯定不是最小的:删除重复,让groupBy简单地设置任何状态值,渲染可以显示愚蠢的状态更改!
for等等。这里仍然有很多代码与您所问的问题无关。(mcve通常要求删除真实代码的所有外观,并纯粹深入到一件对您不起作用的事情)这是一个时间问题。当您定义这样的“静态”属性时,它会被转换/编译到构造函数中(正如在构造函数中定义的那样)。它不是真正的静态。但构造函数中的赋值可能是在您将函数绑定到类之前发生的。@JohnRuddell只是为了正确起见,这不是静态字段定义,而是类字段定义。正如您所说,这只是编写构造函数代码的语法糖分,因为这就是它的最终目的。您的建议但是,很可能是正确的,试图以这种方式绑定此
是不可靠的。
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 });
}