在通过 useState() 更改状态后,我的祖父母没有使用新变量重新呈现查询并显示新数据

Posted

技术标签:

【中文标题】在通过 useState() 更改状态后,我的祖父母没有使用新变量重新呈现查询并显示新数据【英文标题】:My Grandparent is not re-rendering the Query with new variables and displaying new data, after the state changes through useState() 【发布时间】:2021-09-08 18:38:06 【问题描述】:

所以,我遇到了这个问题,我在使用一个 graphql 查询时制作过滤器。有一个孩子,父母和祖父母(这些是不同的组成部分)。现在我的查询在其中使用变量,最初在加载时我将变量设置为 useState 并且它工作正常。现在,当我单击一个复选框(它是 insinde Child 组件)时,它会将其数据(这是新查询的变量)传递给祖父母,我得到了它,所以我将该数据传递给查询变量。但它不会再次使用新变量重新重新查询查询。所以我的过滤器不起作用。

祖父母

// 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 ***************
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 *****************
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 = `$resultproduct_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"
              />
  )

我尝试在 GrandParent 中的 useQuery 上使用 useEffect,但返回的常量无法访问外部,例如

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

非常感谢您的回答^^

【问题讨论】:

【参考方案1】:

所以,我想出了一个解决方案,因为没有人回答,所以我会回答它。

首先,你需要在 useQuery 钩子中添加 refetch 和 fetch-policy as

const  loading, error, data, fetchMore, refetch, networkStatus  = useQuery(
QUERY,

  variables: queryVariables,
  // notifyOnNetworkStatusChange: true,
  fetchPolicy: "network-only"

);

然后,您需要创建一个与传递给孩子的道具同名的单独函数,并使用带有 queryVariables 的扩展运算符来扩展和重新获取带有新变量的查询

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

希望这对某人有帮助^^

【讨论】:

以上是关于在通过 useState() 更改状态后,我的祖父母没有使用新变量重新呈现查询并显示新数据的主要内容,如果未能解决你的问题,请参考以下文章

useState 在 useEffect 中定义后保持初始状态

路由更改时如何清除useState的数据

useState 函数在功能组件中不起作用

useState 设置方法不会立即反映更改

React hooks - useState() 中的状态在路由更改时不会重置

React useState 和 useEffect 混淆