Search code examples
reactjsgraphqlapolloapollo-client

useLazyQuery onCompleted function is not being called


I'm trying to create a basic list when I send a request every time with useLazyQuery.

This is my App component. As you can see, I use network-only fetchPolicy but I still get some problems. Firstly, I delete an item from the list. After I delete an item, I want to add the same value to the list. However, onCompleted has not been called.

Also, onCompleted has not been called again when I try to send the last request. I tried no-cache fetchPolicy but I still get some problems. It's not working properly. What am I doing wrong?

const App = () => {
  const [code, setCode] = useState('');
  const [coins, setCoins] = useState([]);

  const [getData, { loading, data, error }] = useLazyQuery(GET_COIN_PRICE_QUERY, {
    variables: { code },
    fetchPolicy: 'network-only',
    onCompleted: (data) => {
      const hasSameCoin = coins.some((f) => f.id === data.markets[0]?.id);
      if (data.markets.length && !hasSameCoin) {
        setCoins([...coins, data.markets[0]]);
      } else if (data.markets.length <= 0) {
        alert('coin not found');
      }
      if (hasSameCoin) {
        alert('has same value');
      }
    }
  });

  console.log(coins, 'coins');

  return (
    <div>
      <Card setCode={setCode} getData={getData} />
      <CoinList loading={loading} coins={coins} setCoins={setCoins} setCode={setCode} />
    </div>
  );
};

export default App;

This is my Card component.

export const Card = ({ setCode, getData }: Props) => {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (e: any) => {
    setInputValue(e.target.value);
  };

  const onClick = () => {
    if (inputValue) {
      setCode(inputValue);
      setInputValue('');
      getData();
    } else {
      alert('enter a code please');
    }
  };

  return (
    <div className={styles.wrapper}>
      <div>
        <Input placeholder="BTC" value={inputValue} onChange={handleChange} />
      </div>
      <div>
        <Button onClick={onClick}>Add</Button>
      </div>
      <div>
        <div>Use of this service is subject to terms and conditions.</div>
      </div>
    </div>
  )};

Here is my CoinList component.

export const CoinList = ({ loading, coins, setCoins }: Props) => {
  if (loading) {
    return <>Loading...</>;
  }

  const deleteCoin = (id: string) => {
    const filteredCoins = coins.filter((c) => c.id !== id);
    setCoins(filteredCoins);
  };

  return (
    <>
      {coins.map((coin, idx) => {
        return (
          <div className={styles.wrapper} key={`${coin.id}_${idx}`}>
            <div>{coin.baseSymbol}</div>
            <div>{coin.ticker.lastPrice.substring(0, 8)} &euro;</div>

            <div className={styles.delete} onClick={() => deleteCoin(coin.id)}>
              <img src={deleteIcon} alt="deleteIcon" />
            </div>
          </div>
        );
      })}
    </>
  );
};

Solution

  • I fixed it when I added notifyOnNetworkStatusChange into options of useLazyQuery.

      const [getData, { loading, data, error }] = useLazyQuery(GET_COIN_PRICE_QUERY, {
        notifyOnNetworkStatusChange: true,
        variables: { code },
        fetchPolicy: 'network-only',
        onCompleted: (data) => {
         ...
        }
      });