我无法在我的代码中更新状态
我遇到的问题是我的componentDidUpdate()在更新分配时进行API调用后没有更新赋值状态。当我更新列表中特定任务的到期日期时,它会对服务器进行API调用,如果响应成功则返回true。查看状态更新更改的唯一方法是刷新页面。 componentDidUpdate()陷入无限循环,任何人都可以识别出这个下划线的原因吗?
谢谢你的帮助
import * as React from 'react';
import './BundleAssignments.less';
import { IBundles, featureAccessApi, IAssignmentsByFirm, IBundleAssignment } from '@afi/tfs';
import { Loader } from '@afi/tfs';
export interface IOwnProps {}
export interface IOwnState {
loadingBundles: boolean,
loadingAssignments?: boolean,
loadingUpdate?: boolean,
bundles: IBundles[],
assignments: IAssignmentsByFirm[],
expirationDate: string,
bundleId?: number | undefined
}
export class BundleAssignments extends React.Component<IOwnProps, IOwnState> {
constructor(props: IOwnProps) {
super(props);
this.state = {
loadingBundles: true,
bundles: [],
assignments: [],
expirationDate: "",
bundleId: undefined
};
}
public componentDidMount() {
this.loadBundles();
}
public componentDidUpdate(prevProps: IOwnProps, prevState: IOwnState)
{
if (prevState.assignments !== this.state.assignments && this.state.bundleId !== undefined){
this.loadBundleAssignments(this.state.bundleId);
}
}
public render() {
return (
<div className="bundle-assignments">
<h1>Bundle assignments</h1>
{
this.state.loadingBundles ? <Loader /> :
<>
<select onChange={e => this.onChangeSelectedBundle(e)}>
<option value="">-- Select a Bundle --</option>
{
this.state.bundles.map(b =>
<option key={b.id} value={b.id}>{b.name}</option>
)
}
</select>
{
this.state.assignments != null && this.state.assignments.length > 0 ?
(this.state.loadingAssignments || this.state.loadingUpdate) ? <Loader /> :
<>
<h1>Assignments</h1>
<div className="download">
<a href={"https://localhost:44301/api/v2/admin/featureBundle/download/" + this.state.bundleId}>Download Excel</a>
</div>
<table className="assignmentsTable">
{
this.state.assignments.map(a =>
<tr key={a.firmRef}>
<th>
<span>{a.firmName}</span><br />
<a href={"admin/teams/firm/" + a.firmRef}>View teams</a>
</th>
<td>
{
<ul id="entites">
{
a.entities.map(e =>
<li key={e.entityRef}>
<span>{e.entityName}</span>
</li>
)
}
</ul>
}
</td>
<td>
{
a.entities.map(e =>
<form key={e.entityRef} onSubmit={(event) => this.handleSubmit(event, e.bundleAssignment.entityRef, e.bundleAssignment.bundleId, e.bundleAssignment.entityTypeId)}>
<input type="datetime-local" name="expirationDate" defaultValue={e.bundleAssignment.expirationDate} onChange={this.handleInputChange} />
<input type="submit" value="Update" />
</form>
)
}
</td>
</tr>
)
}
</table>
</>
: null
}
</>
}
</div>
)
}
private loadBundles = () => {
featureAccessApi.bundles()
.then(response => this.loadBundlesSuccess(response.bundles));
}
private loadBundlesSuccess = (bundles: IBundles[]) => {
this.setState({ ...this.state,
...{
loadingBundles: false,
bundles: bundles
}
})
}
private onChangeSelectedBundle = (e: React.ChangeEvent<HTMLSelectElement>) => {
const bundleId = Number(e.target.value);
this.setState({ ...this.state, ...{ loadingAssignments: true, bundleId: bundleId } })
this.loadBundleAssignments(bundleId);
}
private handleSubmit = (e: React.FormEvent, entityRef: number, bundleId: number, entityTypeId: number) => {
e.preventDefault();
this.setState({ ...this.state, ...{ loadingUpdate: true }})
this.updateBundleAssignment(entityRef, bundleId, entityTypeId);
}
private handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const target = e.target;
const value = target.value;
const name = target.name;
this.setState({ ...this.state,
...{
[name]: value
}
})
}
private updateBundleAssignment = (entityRef: number, bundleId: number, entityTypeId: number) => {
const request: IBundleAssignment = {
entityRef: entityRef,
bundleId: bundleId,
entityTypeId: entityTypeId,
expirationDate: this.state.expirationDate
};
featureAccessApi.updateBundleAssignment(request)
.then(response => this.bundleAssignmentUpdateSuccess());
}
private bundleAssignmentUpdateSuccess = () =>
this.setState({ ...this.state, ...{ loadingUpdate: false }})
private loadBundleAssignments = (bundleId: number) => {
featureAccessApi.bundleAssignments(bundleId)
.then(response => this.loadBundleAssignmentsSuccess(response.assignmentsByFirms));
}
private loadBundleAssignmentsSuccess = (bundleAssignments: IAssignmentsByFirm[]) => {
this.setState({ ...this.state,
...{
loadingAssignments: false,
assignments: bundleAssignments
}
})
}
}
使用!==
比较数组只会比较数组的引用而不是它们的内容,所以每次更新assignment
数组时,loadBundleAssignments
都会再次运行。
console.log([1,2] !== [1,2])
你可以改用例如Lodash isEqual
检查数组中的所有元素是否相互匹配。
public componentDidUpdate(prevProps: IOwnProps, prevState: IOwnState) {
if (
!_.isEqual(prevState.assignments, this.state.assignments) &&
this.state.bundleId !== undefined
) {
this.loadBundleAssignments(this.state.bundleId);
}
}