当变量未更改或更改为null时,useLazyQuery和useQuery onCompleted无法运行

时间:2020-05-31 15:27:39

标签: graphql react-apollo

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

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

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();
  }; 

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

1 个答案:

答案 0 :(得分: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客户端很聪明,可以从缓存中读取数据,如果数据已经可用,则默认情况下,提取策略为“缓存优先”。