避免过多的重新渲染,循环重新渲染

时间:2021-05-14 10:33:01

标签: reactjs react-hooks rerender react-query

我有一个表,表的每一行 (DifferentialRow) 都使用 react-query 的 useQuery 钩子查询自己的数据。 我希望表格的行按给定的字段值排序(在 DifferentialRow 内计算),并且只显示前 10 行。

<Table.Body>
    {filteredVariables!.map((variable, i) => {
      return variable.show ? (
        <DifferentialRow
          key={i}
          ....
          variable={variable.variable}
          setFilteredVariables={setFilteredVariables}
          
        />
      ) : null;
    })}
  </Table.Body>

因此,当 (DifferentialRow) 行检索其数据并计算排序值时,我使用新行值更新父过滤变量对象,排序,然后使用传入的 setFilteredVariables 为前 10 个设置 show = true DifferentialRow(全部显示如下)。

const diffQuery = useQuery(["differential", {startDate, variable}],fetchDifferentialData);
...
if (diffQuery.isSuccess && diffQuery.data) {
   setSortValue(calcSortValue(diffQuery.data.data));
} 
html rows here

...
function calcSortValue(resultData: any[]) {
    // once we've got a result, and we have calculated the diff we need
    // to set the filteredVariables object that keeps track of cumulative data to only show top x
    try {
      let sortValue = resultData[0].dataValue - resultData[numberOfDays - 1].dataValue;

      setFilteredVariables((prev: { variable: string; diff: number; show: boolean }[]) => {
        let newResults = [...prev, { diff: sortValue, variable, show: undefined }];
        newResults.sort((a, b) => {
          return Math.abs(b.diff || 0) - Math.abs(a.diff || 0);
        });

        let inTopTen = newResults
          .slice(0, 10)
          .map((co) => co.variable)
          .includes(variable);

        let finalResults: CompareObject[];
        if (inTopTen) {
          finalResults = newResults.map((nr) => {
            return nr.variable === variable? { ...nr, show: true }: nr;
          });
        } else {
          finalResults = newResults.map((nr) => {
            return nr.variable === variable? { ...nr, show: false }: nr;
          });
        }
        
        return finalResults;
      });
      return diff;
    } catch (error) {
      return 0;
    }
  }

这都是在创建循环重新渲染,我不知道如何解决它。

1 个答案:

答案 0 :(得分:1)

好的,所以我的解决方案是完全删除 DistributionRow 组件并使用 useQueries(每个查询代表一行)查询父(表)组件中的数据。然后我对 useQueries 的结果进行所有排序和切片。

const diffResults = useQueries(...)

return diffResults.some((dr) => dr.isSuccess) ?  .... <Table.Body>
    {diffResults
      .filter((dr) => dr.isSuccess)
      .map((dr: any) => {
        let dateSorted = dr.data.data.sort(function (a: any, b: any) {
          return new Date(b.runDate).getTime() - new Date(a.runDate).getTime();
        });
        let diff = Math.round(calcDiff(dateSorted) * 10) / 10;

        let fullResult = {
          results: dr.data,
          diff,
        };
        return fullResult;
      })
      .sort((a, b) => {
        return Math.abs(b.diff || 0) - Math.abs(a.diff || 0);
      })
      .slice(0, 10)
      .map(({ diff, results }, i) => {
        return (
          <Table.Row key={i} data-testid="table-row">
            <Table.Cell>{results.variable}</Table.Cell>
            {results.data.map((d: any, i: number) =>
              new Date(d.runDate) > endDate ? (
                <Table.Cell key={i}>
                  {isNaN(d?.dataValue) ? null : Math.round(d?.dataValue * 10) / 10}
                </Table.Cell>
              ) : null
            )}
            {compareColumn ? <Table.Cell>{diff}</Table.Cell> : null}
          </Table.Row>
        );
      })}
  </Table.Body>