如何在使用GraphQL轮询时防止重新渲染

时间:2019-11-24 20:52:28

标签: reactjs graphql react-apollo

我需要使用轮询来使用GraphQL查询数据。但是,只有在数据更改后,react组件才应重新渲染。如何防止每次有新数据传入时重新渲染组件?以下代码不会阻止重新渲染。

  const Instructions: React.FC<RouteComponentProps<RouteParams>> = props => {
  const [firstTimeDataRender, setFirstTimeDataRender] = useState(true);
  const [instructionData, setInstructionData] = useState<FetchSettlementInstructionsQuery_instructions[]>([]);

  const { data, loading, error } = useQuery<FetchSettlementInstructionsQuery, FetchSettlementInstructionsQueryVariables>(
    settlementInstructionsQuery,
    {
      variables: {
        sort: null,
        filter: { type: SettlementInstructionType.freeOfPayment },
      },
      fetchPolicy: 'cache-and-network',
      pollInterval: 5000,
    },
  );

  if (!!data && firstTimeDataRender) {
    setFirstTimeDataRender(false);
    setInstructionData(data.instructions);
  }

  const showLoading = loading && !(!!data && data.members) && firstTimeDataRender;

  if (data && data.instructions !== instructionData) {
    setInstructionData(data.instructions);
  }

  return (
    <LayoutContent>
      <Instructions data={instructionData} loading={showLoading} error={error ? true : false} />
    </LayoutContent>
  );
};

1 个答案:

答案 0 :(得分:0)

您的重新呈现问题应该与加载有关,或者与数据更改的状态更新有关。
我建议此时从状态中删除数据。 我不确定该代码是否可以工作,但是删除了一些无用的东西。 如果仍在重新呈现,请尝试在项目组件级别使用备忘录:

const Memorized = ({ children, rerenderIfThisValueChange = true, orThis = true, id = 0 }) => useMemo(() => children, [rerenderIfThisValueChange, orThis, id]);
<Memorized orThis={instruction.smt} id={instruction.id} >
  <ListItem item={instruction} />
</Memorized>

并返回带有记忆钩的列表项。

const Instructions: React.FC<RouteComponentProps<RouteParams>> = props => {
      const [firstTimeDataRender, setFirstTimeDataRender] = useState(true);

      const { data, loading, error } = useQuery<FetchSettlementInstructionsQuery, FetchSettlementInstructionsQueryVariables>(
        settlementInstructionsQuery,
        {
          variables: {
            sort: null,
            filter: { type: SettlementInstructionType.freeOfPayment },
          },
          fetchPolicy: 'cache-and-network',
          pollInterval: 5000,
        },
      );

      if (firstTimeDataRender) {
        setFirstTimeDataRender(false);
      }

      const showLoading = loading && !(!!data && data.members) && firstTimeDataRender; //  <= The problem should be here

      const { instructions = [] } = data || {}

      return (
        <LayoutContent>
          <Instructions data={instructions} loading={showLoading} error={!!error} />
        </LayoutContent>
      );
    };