useLazyQuery和useQuery onCompleted在变量不更改或更改为null时不运行

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

我想做什么:我有几个类别切换按钮。我只想显示已检查类别的数据。

我的方法:用于显示已过滤数据的功能会检查按钮数组,查看被打勾的按钮,然后读取查询的缓存。

const getFilteredData = () => {
    try {
      const freshFilteredData = []
      for (var i = 0; i < chipData.length; i ++){
          if (chipData[i].clicked){
            const itineraryData = client.readQuery({
              query: GET_ITINERARY,
              variables: {itineraryId : chipData[i].label}
            })
            const wantedData = itineraryData.getItinerary.dayPlans;
            freshFilteredData.push(wantedData)
          }
      }
      setFilteredData(freshFilteredData)
    } catch (err) {
      console.log(err)
    }
  }

但是,只有在触发查询后才能读取缓存。因此,我使用if-else语句来决定何时调用getFilteredData函数。如果仅选中按钮,则我调用查询(完成后将调用getFilteredData函数),如果未选中按钮,则直接调用getFilteredData

  const toggleClick = clickedChip => () => {
    const chipClone = [...chipData];
    const objectIndex = chipData.findIndex(
      chip => chip.key === clickedChip.key
    );
    chipClone[objectIndex].clicked = !chipData[objectIndex].clicked;
    setChipData(chipClone);

    if (chipClone[objectIndex].clicked) {
      getItinerary({variables: {itineraryId: clickedChip.label}});
    } else {
      console.log('fire2')
      getFilteredData();
    }
  };

这是我的懒惰查询:

const [getItinerary] = useLazyQuery(GET_ITINERARY, {
    onCompleted(data){
      console.log('fired');
      getFilteredData()
    }
  });

我的问题:如果我单击同一按钮三次。

  1. 点击(运行查询)
  2. 未单击(不运行查询)
  3. 单击(不运行查询,因此不运行getFilteredData函数,因为查询不运行onCompleted。而且由于单击了它,所以它也不会执行“ else”语句,因此getFilteredData根本不会运行)

这搞砸了过滤。

我可能摆脱if-else语句,并在两个位置执行getFilteredData函数:

const toggleClick = clickedChip => () => {
    const chipClone = [...chipData];
    const objectIndex = chipData.findIndex(
      chip => chip.key === clickedChip.key
    );
    chipClone[objectIndex].clicked = !chipData[objectIndex].clicked;
    setChipData(chipClone);

    getItinerary({variables: {itineraryId: clickedChip.label}});
    getFilteredData();
  }; 

这将涵盖所有基础,但我想知道是否还有更优雅的方法?

graphql react-apollo
1个回答
0
投票

默认情况下,您错过的是阿波罗,所有已发出查询的结果都存储在其本地缓存中,任何随后的查询调用都会从缓存中获取结果(除非您已更改提取策略)。

而不是我们手动检查是否是首次呼叫,而是将这一责任委托给阿波罗。

我对流程的建议是

1)维护所单击的芯片标签的状态变量

2)在芯片的onClick回调中更改上述标签,这将触发查询

3)让阿波罗决定是第一次呼叫还是随后的呼叫

 const [chipLabel, setChipLabel] = useState(<Initial label here>) // pass the initial value 
//that query expects

    // pass the state variable above in the query
    const itineraryData = useQuery({
                  query: GET_ITINERARY,
                  variables: {itineraryId : chipLabel}
                })

    // all the toggle button should have a click handler like below
    onClick={() =>{//call the setChipLabel}}

打开网络选项卡,多次单击任何过滤器按钮,只有在第一次单击期间,才会发出n / w呼叫。 Apollo客户端很聪明,可以从缓存中读取数据,如果数据已经可用,则默认情况下,提取策略为“缓存优先”。

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