更新道具不会调用 componentWillReceiveProps 方法
Updating props doesn't invoke componentWillReceiveProps method
在 UI 中,我有两个按钮,addRow 和 removeRow。 AddRow 添加带有下拉菜单的新行,removeRow 删除它们。出于某种原因,单击删除行不会从 UI 中删除该行。
父级 class 是功能组件:
export const LimitUpdateSRCreate: React.FC<Props> = (props) => {
const [defaultCategory, setDefaultCategory] = React.useState<string>(
undefined
);
const [defaultResource, setDefaultResource] = React.useState<string>(
undefined
);
const [limitFields, setLimitFields] = React.useState<ResourceLimitFields[]>(
[]
);
const [resourceInputRows, setResourceInputRows] = React.useState<
ResourceInputRow[]
>([]);
return (
<LimitRequestInputList
serviceCategoryTestId="sr-service-select-id"
resourceTestId="sr-resource-select-id"
defaultCategory={defaultCategory}
defaultResource={defaultResource}
setGeneratedFields={setLimitFields}
setResourceLimitRows={setResourceInputRows}
rows={resourceInputRows}
generatedFields={limitFields}
incidentTypes={
!!incidentTypes.response ? incidentTypes.response.data : []
}
/>
)
};
LimitRequestInputList 组件是一个 class 组件,它有 addRow 和 removeRow 按钮:
export class LimitRequestInputList extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
nextId : 0
};
}
public componentDidMount(): void {
this.createDefaultRow(this.props);
}
private createDefaultRow(otherProps: Props): void {
if (otherProps && otherProps.incidentTypes && otherProps.incidentTypes.length && !otherProps.rows.length) {
const firstId = 0;
const defaultRow = [
{ id: firstId,
row: (
<ResourceLimitIncreaseRow
serviceCategoryTestId={otherProps.serviceCategoryTestId}
resourceTestId={otherProps.resourceTestId}
rowId={firstId}
key={"" + firstId}
isDefaultRow={true}
defaultCategory={otherProps.defaultCategory}
defaultResource={otherProps.defaultResource}
setGeneratedFields={this.setGeneratedFields}
formRef={otherProps.formRef}
incidentTypes={otherProps.incidentTypes}
removeRow={this.removeRow}
/>)
}];
this.addGeneratedFields(firstId);
this.setState ({
nextId : firstId + 1
});
this.props.setResourceLimitRows(defaultRow);
}
}
public componentWillReceiveProps(nextProps: Props): void {
this.createDefaultRow(nextProps);
}
private addRow = (): void => {
const newNextId = this.state.nextId + 1;
const currentRows = this.props.rows;
currentRows.push({ id: this.state.nextId, row: (
<ResourceLimitIncreaseRow
serviceCategoryTestId={this.props.serviceCategoryTestId}
resourceTestId={this.props.resourceTestId}
key={"" + this.state.nextId}
rowId={this.state.nextId}
isDefaultRow={false}
setGeneratedFields={this.setGeneratedFields}
formRef={this.props.formRef}
incidentTypes={this.props.incidentTypes}
removeRow={this.removeRow}
/>
)});
this.addGeneratedFields(this.state.nextId);
this.setState({ nextId: newNextId });
this.props.setResourceLimitRows(currentRows);
}
private removeRow = (rowId: number): void => {
const rows = this.props.rows;
const currentRow = rows ? rows.findIndex(row => row.id === rowId) : -1;
if (currentRow !== -1) {
rows.splice(currentRow, 1);
this.props.setResourceLimitRows(rows);
}
this.removeGeneratedFields(rowId);
}
private addGeneratedFields = (rowId: number): void => {
const newGeneratedFieldsRow: ResourceLimitFields = {
id: rowId,
serviceCategoryFieldName: ServiceCategoryFieldName + rowId,
resourceFieldName: ResourceFieldName + rowId,
generatedFields: []
};
const newGeneratedFields = this.props.generatedFields;
newGeneratedFields.push(newGeneratedFieldsRow);
this.props.setGeneratedFields(newGeneratedFields);
}
private removeGeneratedFields = (rowId: number): void => {
const generatedFieldRows = this.props.generatedFields;
const currentRow = generatedFieldRows ? generatedFieldRows.findIndex(row => row.id === rowId) : -1;
if (currentRow !== -1) {
generatedFieldRows.splice(currentRow, 1);
this.props.setGeneratedFields(generatedFieldRows);
}
}
private getResourceRows = (): JSX.Element[] => {
const resourceRows : JSX.Element[] = this.props.rows.map(resourceRow => resourceRow.row);
return resourceRows;
}
private setGeneratedFields = (resourceLimitFields: ResourceLimitFields) : void => {
const generatedFieldRows = this.props.generatedFields;
const currentRowIndex = generatedFieldRows ?
generatedFieldRows.findIndex(row => row.id === resourceLimitFields.id) : -1;
if (currentRowIndex === -1) {
generatedFieldRows.push(resourceLimitFields);
} else {
generatedFieldRows[currentRowIndex].generatedFields = resourceLimitFields.generatedFields;
}
this.props.setGeneratedFields(generatedFieldRows);
}
}
据我所知,只要道具发生变化,就会调用 componentWillReceiveProps 方法。在我的代码中,那没有发生。问题是因为父项是功能组件,而子项是 class 组件。我想应该不是个例。因此,单击删除按钮不会从 UI 中删除该行。 componentWillReceiveProps 没有被调用的原因可能是什么?我确保每次单击按钮时道具值都不同。
你正在改变 remove 方法中的 rows
道具,最好使用过滤器将其删除:
private removeRow = (rowId: number): void => {
const rows = this.props.rows.filter(r => r.id !== rowId);
this.props.setResourceLimitRows(rows);
this.removeGeneratedFields(rowId);
}
当您执行 const rows = this.props.rows;
时,新的 rows
变量仍然指向 this.props.rows
并且对它的所有更改都会反映在 this.props.rows
.
另一种方法是在修改 rows
.
之前通过 const rows = this.props.rows.concat()
或 const rows = this.props.rows.slice()
制作 props 数组的浅表副本
在 UI 中,我有两个按钮,addRow 和 removeRow。 AddRow 添加带有下拉菜单的新行,removeRow 删除它们。出于某种原因,单击删除行不会从 UI 中删除该行。 父级 class 是功能组件:
export const LimitUpdateSRCreate: React.FC<Props> = (props) => {
const [defaultCategory, setDefaultCategory] = React.useState<string>(
undefined
);
const [defaultResource, setDefaultResource] = React.useState<string>(
undefined
);
const [limitFields, setLimitFields] = React.useState<ResourceLimitFields[]>(
[]
);
const [resourceInputRows, setResourceInputRows] = React.useState<
ResourceInputRow[]
>([]);
return (
<LimitRequestInputList
serviceCategoryTestId="sr-service-select-id"
resourceTestId="sr-resource-select-id"
defaultCategory={defaultCategory}
defaultResource={defaultResource}
setGeneratedFields={setLimitFields}
setResourceLimitRows={setResourceInputRows}
rows={resourceInputRows}
generatedFields={limitFields}
incidentTypes={
!!incidentTypes.response ? incidentTypes.response.data : []
}
/>
)
};
LimitRequestInputList 组件是一个 class 组件,它有 addRow 和 removeRow 按钮:
export class LimitRequestInputList extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
nextId : 0
};
}
public componentDidMount(): void {
this.createDefaultRow(this.props);
}
private createDefaultRow(otherProps: Props): void {
if (otherProps && otherProps.incidentTypes && otherProps.incidentTypes.length && !otherProps.rows.length) {
const firstId = 0;
const defaultRow = [
{ id: firstId,
row: (
<ResourceLimitIncreaseRow
serviceCategoryTestId={otherProps.serviceCategoryTestId}
resourceTestId={otherProps.resourceTestId}
rowId={firstId}
key={"" + firstId}
isDefaultRow={true}
defaultCategory={otherProps.defaultCategory}
defaultResource={otherProps.defaultResource}
setGeneratedFields={this.setGeneratedFields}
formRef={otherProps.formRef}
incidentTypes={otherProps.incidentTypes}
removeRow={this.removeRow}
/>)
}];
this.addGeneratedFields(firstId);
this.setState ({
nextId : firstId + 1
});
this.props.setResourceLimitRows(defaultRow);
}
}
public componentWillReceiveProps(nextProps: Props): void {
this.createDefaultRow(nextProps);
}
private addRow = (): void => {
const newNextId = this.state.nextId + 1;
const currentRows = this.props.rows;
currentRows.push({ id: this.state.nextId, row: (
<ResourceLimitIncreaseRow
serviceCategoryTestId={this.props.serviceCategoryTestId}
resourceTestId={this.props.resourceTestId}
key={"" + this.state.nextId}
rowId={this.state.nextId}
isDefaultRow={false}
setGeneratedFields={this.setGeneratedFields}
formRef={this.props.formRef}
incidentTypes={this.props.incidentTypes}
removeRow={this.removeRow}
/>
)});
this.addGeneratedFields(this.state.nextId);
this.setState({ nextId: newNextId });
this.props.setResourceLimitRows(currentRows);
}
private removeRow = (rowId: number): void => {
const rows = this.props.rows;
const currentRow = rows ? rows.findIndex(row => row.id === rowId) : -1;
if (currentRow !== -1) {
rows.splice(currentRow, 1);
this.props.setResourceLimitRows(rows);
}
this.removeGeneratedFields(rowId);
}
private addGeneratedFields = (rowId: number): void => {
const newGeneratedFieldsRow: ResourceLimitFields = {
id: rowId,
serviceCategoryFieldName: ServiceCategoryFieldName + rowId,
resourceFieldName: ResourceFieldName + rowId,
generatedFields: []
};
const newGeneratedFields = this.props.generatedFields;
newGeneratedFields.push(newGeneratedFieldsRow);
this.props.setGeneratedFields(newGeneratedFields);
}
private removeGeneratedFields = (rowId: number): void => {
const generatedFieldRows = this.props.generatedFields;
const currentRow = generatedFieldRows ? generatedFieldRows.findIndex(row => row.id === rowId) : -1;
if (currentRow !== -1) {
generatedFieldRows.splice(currentRow, 1);
this.props.setGeneratedFields(generatedFieldRows);
}
}
private getResourceRows = (): JSX.Element[] => {
const resourceRows : JSX.Element[] = this.props.rows.map(resourceRow => resourceRow.row);
return resourceRows;
}
private setGeneratedFields = (resourceLimitFields: ResourceLimitFields) : void => {
const generatedFieldRows = this.props.generatedFields;
const currentRowIndex = generatedFieldRows ?
generatedFieldRows.findIndex(row => row.id === resourceLimitFields.id) : -1;
if (currentRowIndex === -1) {
generatedFieldRows.push(resourceLimitFields);
} else {
generatedFieldRows[currentRowIndex].generatedFields = resourceLimitFields.generatedFields;
}
this.props.setGeneratedFields(generatedFieldRows);
}
}
据我所知,只要道具发生变化,就会调用 componentWillReceiveProps 方法。在我的代码中,那没有发生。问题是因为父项是功能组件,而子项是 class 组件。我想应该不是个例。因此,单击删除按钮不会从 UI 中删除该行。 componentWillReceiveProps 没有被调用的原因可能是什么?我确保每次单击按钮时道具值都不同。
你正在改变 remove 方法中的 rows
道具,最好使用过滤器将其删除:
private removeRow = (rowId: number): void => {
const rows = this.props.rows.filter(r => r.id !== rowId);
this.props.setResourceLimitRows(rows);
this.removeGeneratedFields(rowId);
}
当您执行 const rows = this.props.rows;
时,新的 rows
变量仍然指向 this.props.rows
并且对它的所有更改都会反映在 this.props.rows
.
另一种方法是在修改 rows
.
const rows = this.props.rows.concat()
或 const rows = this.props.rows.slice()
制作 props 数组的浅表副本