My Grandparent is not re-rendering the Query with new variables and displaying new data, after the state changes through useState()

So, I am running into this problem where I am making filters while using the one graphql query. There’s a child, parent & grandparent(these are different components). Now my query uses variables inside it, initially on load I set the variables in useState and it’s working fine. Now when I click on a checkbox(which is insinde Child component) it passed its data(which is variable for new query) to the Grandparent and I am getting that, so I pass that data into the query variable. But it’s not re-redering the query again with new variable. So my filters are not working.

Grand Parent

// handling all the product grid actions and data
function ProductGrid() {

  const [queryVariables, setQueryVariables] = useState({first: 20});
  console.log(queryVariables);
  // get the variable object

  
  const { loading, error, data, fetchMore} = useQuery(QUERY, {
    variables: queryVariables
  });

   
  if (loading) return <p>Loading...</p>;
  if (error) return (
    <p>
    {console.log(error)}
    </p>
  );

  let productEdges = data.products.edges;
  return(
    <div className="outContainer">
      {/* <PriceFilter/> */}
      <TypeFilter getFilters={queryVariables => setQueryVariables(queryVariables)} />
      {/* test button */}
      <div className="product-grid">
        {productEdges.map((element, index) => {
          
          // formatting the price
          let tempPrice = Math.floor(element.node.priceRange.minVariantPrice.amount);
          let productPrice = new Intl.NumberFormat().format(tempPrice);

          return(
              <div className="container" key={index}>
                <div className="image-container">
                  <img src={element.node.images.edges[0].node.transformedSrc} alt={element.node.title} />
                </div>
                <div className="product-title">{element.node.title}</div>
                <div>{element.node.priceRange.minVariantPrice.currencyCode}. {productPrice}</div>
              </div>

          ) 
        })}
      </div>
      {/* load more products button */}
      <button
        className="load-more"
        onClick={()=>{
          const endCursor = data.products.edges[data.products.edges.length - 1].cursor;
          
          fetchMore({
            variables: {
              after: endCursor,
              queryVariables
            }
          })
        }}>
          Load More
        </button>
    </div>
  )
}

// graphql query for products fetching
const QUERY = gql`
query productFetch($first:Int, $after:String, $query:String){
  products(first:$first, after: $after, query:$query){
    edges{
      node{
        priceRange{
          minVariantPrice{
            amount
            currencyCode
          }
        }
        title
        images(first:1){
          edges{
            node{
              transformedSrc(maxWidth: 300)
            }
          } 
        }
        
      }
      cursor
    }
    pageInfo{
      hasNextPage
    }
  }
}

`

Parent

// ************** Parent ***************
function TypeFilter(props) {
  // assume other code is here for a modal pop and 
     accordion inside here
  
  // passing the prop to checkbox component here and 
     getting back new state which we use as a callback for 
     it's parent
  <TypeCheckBox getCheckState={queryVariables => 
  props.getFilters(queryVariables)} />
}

Child

// ************** Child *****************
let result = "";
let variables = 
  {
    first: 28,
    query: ""
  };
function TypeCheckBox(props){
  // below function returns variables for apollo query
    const handleCheckChange = (event) => {
        setState({ ...state, [event.target.name]: event.target.checked });
        if(event.target.checked){
            // pass this value into the productGrid component
            if(counter > 1){
              result += "&";
            }
            result = `${result}product_type:${event.target.value}`;
            counter++;
            // setting filter type to result
            console.log(result);
            variables.query = result;
            console.log(variables);
            return props.getCheckState(variables);
        }else{

          result = result.replace(`product_type:${event.target.value}`, "");
          result = removeLast(result, "&");
          counter--;
          // setting filter type to result
          console.log(`in else ${result}`);
          variables.query = result;
          console.log(variables);
          return props.getCheckState(variables);
        }
    };
  

}
  return (
            <FormGroup column>
              <FormControlLabel
                control={<Checkbox checked={state.checkedBridal} value="Bridal" onChange={handleCheckChange} name="checkedBridal" />}
                label="Bridals"
              />
  )
}

I tried using useEffect on useQuery in GrandParent, but then the returned constants don’t have access outside, like

    useEffect(() => { 
    const { loading, error, data, fetchMore} = useQuery(QUERY, {
        variables: queryVariables
      });
  }, [queryVariables])

Thanks you soo much for your answers ^^

Answer

So, I figured out a solution since no one answered it so I am gonna answer it.

first, you need to add refetch and fetch-policy in useQuery hook as

const { loading, error, data, fetchMore, refetch, networkStatus } = useQuery(
QUERY,
{
  variables: queryVariables,
  // notifyOnNetworkStatusChange: true,
  fetchPolicy: "network-only"
}
);

Then you need to make a separate function with the same name as your props that you’re passing to your children and use the spread operator with queryVariables to expand and refetch the query with new variables as

const getFilters = queryVariables => {
 setQueryVariables({ ...queryVariables });
 refetch();
};

Hope this is helpful to someone ^^