在useEffect内部更新状态后重新加载React组件

问题描述 投票:0回答:1

我有一个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语句等待直到代理商数组被实际填满?

reactjs react-hooks mobx mobx-react
1个回答
0
投票

啊,好吧,如果您想保持相对相似,让我建议您简化一下:

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更新时,它将重新呈现。我们不需要在异步效果内进行调用-每当数据返回时,组件都会重新渲染。

© www.soinside.com 2019 - 2024. All rights reserved.