我有一个react组件,我正在Mobx中更新一个状态,并希望在更新此状态时重新加载相同的组件。我有一个代理商列表,我使用一个组件中的查询参数按类型获取代理商,并基于查询参数从DB中获取过滤数据。
我的组件代码如下:
export interface IListAgenciesProps {
agencyType: string;
agencyTypeTitle: string;
}
const ListAgencies = (props: any) => {
let ctx = useContext(imsStore);
let agencies: IAgency[] = [];
useEffect(() => {
const agencyType = props.match.params["AgencyType"];
ctx.setAgency(agencyType);
async function agencyLoad(){
await ctx.loadAgencies();
agencies = ctx.agencies;
}
agencyLoad();
},
[agencies]);
let html: JSX.Element;
if (agencies.length > 0) {
html = ( <Container>
<Table celled selectable>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Agency Name</Table.HeaderCell>
<Table.HeaderCell>Telephone</Table.HeaderCell>
<Table.HeaderCell>Email</Table.HeaderCell>
<Table.HeaderCell>Is Active?</Table.HeaderCell>
<Table.HeaderCell>Hourly Rate</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{agencies.map(a => {
return (
<Table.Row>
<Table.Cell>{a.name}</Table.Cell>
<Table.Cell>{a.telephone}</Table.Cell>
<Table.Cell>{a.email}</Table.Cell>
<Table.Cell>{a.isActive}</Table.Cell>
<Table.Cell>{a.pricePerHour}</Table.Cell>
</Table.Row>
);
})}
</Table.Body>
</Table>
</Container>
);
} else {
html = ( <Container>
<Header as='h1'>
Sorry, we couldn't find the agency type you're looking for.
</Header>
</Container>
);
}
return <>{html}</>;
};
export default observer(ListAgencies);
在我的IMSStore.ts中,看起来像这样:
@observable agencies: IAgency[] = [];
@action loadAgencies = async () => {
this.agencies = [];
try {
const agencies = await agent.Agencies.list(this.agencyType);
agencies.forEach(agency => {
this.agencies.push(agency);
});
} catch (err) {
console.log(err);
} finally {
}
};
但是,执行return语句时,我的第一个代码段中的agency数组始终为空。因此,每次useEffect运行时,它都会调用loadAgencies,在loadAgencies中,它将代理的值重置为一个空数组。然后执行return语句。我该如何使return语句等待直到代理商数组被实际填满?
啊,好吧,如果您想保持相对相似,让我建议您简化一下:
export interface IListAgenciesProps {
agencyType: string;
agencyTypeTitle: string;
}
const ListAgencies = (props: any) => {
const agencyType = props.match.params["AgencyType"];
const ctx = useContext(imsStore);
const { agencies, loadAgencies } = ctx;
useEffect(() => {
loadAgencies(agencyType);
}, [agencyType]);
let html: JSX.Element;
if (agencies.length > 0) {
html = ( <Container>
<Table celled selectable>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Agency Name</Table.HeaderCell>
<Table.HeaderCell>Telephone</Table.HeaderCell>
<Table.HeaderCell>Email</Table.HeaderCell>
<Table.HeaderCell>Is Active?</Table.HeaderCell>
<Table.HeaderCell>Hourly Rate</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{agencies.map(a => {
return (
<Table.Row>
<Table.Cell>{a.name}</Table.Cell>
<Table.Cell>{a.telephone}</Table.Cell>
<Table.Cell>{a.email}</Table.Cell>
<Table.Cell>{a.isActive}</Table.Cell>
<Table.Cell>{a.pricePerHour}</Table.Cell>
</Table.Row>
);
})}
</Table.Body>
</Table>
</Container>
);
} else {
html = ( <Container>
<Header as='h1'>
Sorry, we couldn't find the agency type you're looking for.
</Header>
</Container>
);
}
return <>{html}</>;
};
export default observer(ListAgencies);
商店:
@observable agencies: IAgency[] = [];
@action loadAgencies = async (agencyType) => {
try {
this.agencies = await agent.Agencies.list(agencyType);
} catch (err) {
console.log(err);
} finally {
}
};
所以现在发生的是我们正在简化组件,以便将agencyType
保存在安装中。然后在deps数组中为效果指定它意味着每次参数改变时我们都调用loadAgencies
。注意,我们现在使用参数调用ctx
方法。因此,loadAgencies
将采用该类型,去获取数据,然后将其设置为所有在同一@action
内部的上下文变量。
然后,因为我们已经从组件内部的agencies
中取消引用ctx
,所以当agencies
@observable
更新时,它将重新呈现。我们不需要在异步效果内进行调用-每当数据返回时,组件都会重新渲染。