React native React Native hook如何使用无状态组件中的hook有条件地更新Flatlist数据?

React native React Native hook如何使用无状态组件中的hook有条件地更新Flatlist数据?,react-native,react-hooks,react-native-flatlist,use-effect,use-state,React Native,React Hooks,React Native Flatlist,Use Effect,Use State,在我们继续之前,我知道在无状态组件中使用钩子的基本原则 仅在顶层调用钩子:不要在循环、条件或嵌套函数中调用钩子 仅从React函数调用钩子:从React函数组件中调用钩子,而不仅仅是任何常规javascript函数 有了这些,以下是我想要实现的目标: 我有目录页,上面有一个平面列表。它显示从目录api获取的所有产品列表 我在Flatlist上面有一个二进制选项开关,用于启用/禁用使用公共键对数组中的项进行分组 我希望flatlist根据是否启用分组(即条件渲染项)动态更改渲染项 有了这些,让

在我们继续之前,我知道在无状态组件中使用钩子的基本原则

  • 仅在顶层调用钩子:不要在循环、条件或嵌套函数中调用钩子
  • 仅从React函数调用钩子:从React函数组件中调用钩子,而不仅仅是任何常规javascript函数
  • 有了这些,以下是我想要实现的目标:

    • 我有目录页,上面有一个平面列表。它显示从目录api获取的所有产品列表
    • 我在Flatlist上面有一个二进制选项开关,用于启用/禁用使用公共键对数组中的项进行分组
    • 我希望flatlist根据是否启用分组(即条件渲染项)动态更改渲染项
    有了这些,让我们看看我的代码。下面是我的用例的完整代码:

    import React, { useState, useEffect } from "react";
    ------ /** imports from other libraries **/ ------
    
    export default function Catalogue({ navigation }){
      const url = 'http://url to the api'
      const token = 'authentication token for the api'
      
      //products array will be displayed using Flatlist & groupby filter will be applied
      const [products, setProducts] = useState([]);
      
      //catalogue array will hold all the original data fetched from the api. 
      //Is used to reset products with original data if needed
      const [catalogue, setCatalogue] = useState([]);
    
      const [groupBy, setGroupBy] = useState("model");
      const onChangeGroup = (value) => setGroupBy(value);
    
      //Function to fetch data from the api
      useEffect(() => {
        async function getCatalogue() {
          const response = await Axios.get(url, {
            headers: { Authorization: token },
          });
          if (response.data.tokenExpired) {
            alert("Session has expired");
            return;
          }
          setProducts(response.data.data);
          setCatalogue(response.data.data);
        }
        getCatalogue();
      }, []);
    
      useEffect(() => {
        console.log("products updated", products);
      }, [products]);
      
      //Call the handle function when state is changed by the switch
      useEffect(() => {
        console.log("groupby updated from useEffect", groupBy);
        handleGroupBy();
      }, [groupBy]);
      
      //Function which returns either original data or grouped items array
      const handleGroupBy = async () => {
        console.log("function called");
        if (groupBy == "model") {
          await setProducts(catalogue); //return original api data
        } else if (groupBy == "manufactor") {
          console.log("entered logic");
          //Logic for grouping items in an array
          const key = "designNumber";
          const groupedList = await catalogue.reduce(
            (hash, object) => ({
              ...hash,
              [object[key]]: (hash[object[key]] || []).concat(object),
            }),
            {}
          );
          console.log("grouped array", groupedList);
          setProducts(groupedList);
        }
      };
      
      return(
        <View>
          <DualSwitch
            initialValue={0}
            onPress{(value) => onChangeGroup(value)}
            options={[
              { label: "Model ", value: "model" },
              { label: "Manufacturer ", value: "manufactor" },
            ]}
          />
          <FlatList
            key={orientation}
            numColumns={isPhone ? phoneColumns : tabletColumns}
            style={styles.flatList}
            columnWrapperStyle={styles.flatlistColums}
            data={products}
            extraData={groupBy}
            keyExtractor={(item) =>
              groupBy == "model" ? item.model : item.manufacturer
            }
            renderItem={({ item }) => 
              groupBy == "model" ? (
                <ProductCatalogueItem item={item} navigation={navigation} />
              ) : (
                <GroupedItem item={item} navigation={navigation} />
              )
            }
          />
        <View/>
      )
    }
    
    在应用程序崩溃后,我得到的错误是:

    所以请帮帮我,我不知道为什么应用程序会崩溃。我只调用if条件中状态变量的setter函数。这些afaik不被视为挂钩,也不违反React挂钩的两个基本原则。你知道哪里出了问题吗

    //1. Component is mounted
    products updated Array []
    
    groupby updated from useEffect modal
    
    function called
    
    //2. data is fetched from the api
    products updated Array []
    
    products updated Array [
      //whole list of objects from the api
    ]
    
    //3. Flatlist gets loaded
    //4. I flick the switch from Model to Manufacturer
    groupby updated from useEffect manufactor
    
    /**App Crashes right here **/
    
    function called
    
    entered logic
    
    grouped array Object {
      "key 1": Array [
        Object {
          item 1
        },
        Object {
          item 4
        },
        Object {
          item 5
        },
      ],
      "key 2": Array [
        Object {
          item 2
        },
        Object {
          item 3
        },
      ]
    }
    
    products updated Object {
      "key 1": Array [
        Object {
          item 1
        },
        Object {
          item 4
        },
        Object {
          item 5
        },
      ],
      "key 2": Array [
        Object {
          item 2
        },
        Object {
          item 3
        },
      ]
    }
    
    //This here is the MOST Bizzare behaviour. the useEffect hooks are called again! like why?
    products updated Array[]
    
    groupby updated from useEffect modal
    
    function called