【问题标题】:Infinite loop in react native hook反应本机钩子中的无限循环
【发布时间】:2021-08-19 11:23:41
【问题描述】:

我正在开发一个 React Native 应用程序。

在我的主要组件中,我使用 UseEffect 挂钩将数据库响应存储在“食物”变量中。然后,我将使用此变量中包含的数据创建一个列表。

这是我的钩子:

const [ food, setFood ] = useState([]);
const [listData, setListData] = useState([]);

const load_food = async () => {
    db.listProduct().then(row => setFood(row))

    setListData(
        Array(food.length)
            .fill('')
            .map((_, i) => ({ key: `${i}`, product: `${food[i].PRODUCTNAME}`,
                                    date: `${food[i].DATE}`,
                                    uri: `${food[i].IMAGEURL}`,
                                    id: `${food[i].IDPRODUCT}`})))
};
useEffect( () => { load_food(food) }, [food] );

但问题是这个钩子被无限期地调用。如果我将 console.log('test') 放在钩子中,日志将是无限的。 因此,我的应用程序非常滞后

根据我对类似问题的理解,我必须在我的钩子中留下一个空数组,如下所示:

useEffect( () => { load_food(food) }, [] );

但是这样做,我的列表没有初始化。

我找不到解决办法

【问题讨论】:

  • 你好,你可以试试这个方法setListData(food.map((item,i)=>{key:i,product:item.PRODUCTNAME,date: item.DATE,uri:item.IMAGEURL,id:item.IPRODUCT}));
  • 您好,感谢您的回答。不幸的是它不起作用,我仍然有一个无限循环
  • 嗨@Fedour你能试试这个代码stackoverflow.com/a/62490696/13725816

标签: reactjs react-native expo


【解决方案1】:

useEffect( () => { load_food(food) }, [food] );这是错误的,这里您需要使用 props 值来更新状态,而不是使用另一个状态值来更新组件,代替 [food] ,将其设为 [] 并在下面使用 useEffect。我想这应该可以工作,否则请检查逻辑是否在您进行 setListData 调用时返回正确的值。

useEffect (() => {
db.listProduct().then(row => setFood(row))

    setListData(
        Array(food.length)
            .fill('')
            .map((_, i) => ({ key: `${i}`, product: `${food[i].PRODUCTNAME}`,
                                    date: `${food[i].DATE}`,
                                    uri: `${food[i].IMAGEURL}`,
                                    id: `${food[i].IDPRODUCT}`})))

},[])

【讨论】:

  • 您好,感谢您的回答。不幸的是,它不起作用。该列表仍然为空。我认为存在同步问题。我会继续搜索。
【解决方案2】:

你可以试试这个方法

const [ food, setFood ] = useState([]);

const [listData, setListData] = useState([]);

const load_food = async () => {
  const row = await db.listProduct();
  setFood(row);

  setListData(row.map(
     (item,i) => ({ 
       key: i, 
       product: item.PRODUCTNAME,
       date: item.DATE,
       uri:item.IMAGEURL,
       id:item.IPRODUCT
      })));

useEffect( () => { load_food() }, [] );

【讨论】:

  • 那行不通。 listData 保持为空...我找到了一个解决方案,将我的钩子分成 2 个不同的钩子
【解决方案3】:

这是一个迟到的回应,但我认为值得解释一下。

您传递的第二个参数 [food] 是告诉 react 在每次更改“food”变量时重新渲染。您的组件无限重新渲染的事实意味着“食物”在不断变化。如果您想要对 load_food 进行一次调用,那么当您提到应该传入第二个参数或仅传递 [] 时,您是正确的。

附带说明,我无法测试代码,但我的假设是这一行: db.listProduct().then(row => setFood(row)) 导致无限循环,因为您正在生成一个新数组并无限更新食物,这就是无限调用 load_food 的原因。

我猜测为什么传入 [] 不起作用是因为您正在更新食物状态变量,然后您立即尝试使用该食物状态变量,假设状态已更新。 setFood 是一个异步函数,这意味着您不能保证立即更新变量。对此有两个修复:

  1. 将初始食物状态设置为您从数据库中检索到的任何数组。但是,这将要求您在第一次呈现组件时从数据库中检索,而这可能不是您想要的。
  2. 不要使用您检索到的任何数组来更新食物,而是将该数组存储到某个临时变量中(例如 db.listProduct().then(row => tmpArray)。然后您可以调用 setFood(tmpArray),更新您的食物变量,然后您可以使用 tmpArray 而不是 food 来调用 setListData,因为 tmpArray 保证是您要使用的数组。

【讨论】:

    猜你喜欢
    • 2021-04-10
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多