在 useEffect 中更新状态后重新加载反应组件

Reload react component after updating state inside useEffect

我有一个 React 组件,我正在更新 Mobx 中的状态,并希望在更新此状态时重新加载相同的组件。我有一个代理列表,我在一个组件中使用查询参数按类型获取代理,并基于我想从数据库中获取过滤数据的查询参数。

我的组件代码如下所示:

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 语句时,我的第一个代码片段中的代理数组始终为空。因此,每次 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 内的上下文变量。

然后,由于我们在组件内部从 ctx 中取消引用 agencies,因此当 agencies @observable 更新时它将重新呈现。我们不需要在效果异步中进行调用 - 只要数据返回,组件就会重新渲染。