使用 useEffect 和 useState 的挑战

huangapple go评论70阅读模式
英文:

Challenges with useEffect, useState

问题

我认为目前我的代码行为似乎是prepareList没有及时更新,因此未定义,然后代码出错,显示filter不是一个函数,并且如果没有prepareList.length,它会返回finalGroups,我确信prepareList内部的映射本身有效,removedSubstitutesList后面有值(对象数组),它本身是useState数组。

正如您所看到的,我已经尝试通过添加完全无关的useEffectmakeWay以及在其中执行setWait来防止这种行为,只是为了等待更长时间以获取到prepareList的值。此外,依赖项列表是尝试让它以某种方式工作以查看出错的一部分。

**我的问题是:**我的reduce函数本身是否有问题,因此它不起作用,或者它确实是useState、多次渲染等的问题,因此在没有值的情况下reducer函数运行得太早,或者还有其他我没有注意到的问题。

此代码是更大代码集的一部分,此部分旨在收集、处理并将准备好的数据提升到主应用程序组件以供其使用。Sendpressed在这里是一个按钮点击事件,liftSubstitutes和liftSubstituteGroups是将数据发送到主应用程序组件的回调函数。

希望我已经足够清楚,以便您可以跟进,如果不清楚,我会尽力指导您。欢迎任何建议,提前感谢。

 useEffect(() => {
    const makeWay = () => {
      setWait('a');
    };
    makeWay();
  }, [sendPressed, finalGroups, removedSubstitutesList]);

  useEffect(() => {
    const liftFinalData = () => {
      const prepareList = removedSubstitutesList.map(item => item.email);
      const finalResults = !prepareList.length
        ? finalGroups
        : prepareList.reduce(
            (results, filter) => results.filter(filter),
            finalGroups[0].data
          );

      liftSubstitutes(Substitutes || 0);
      liftSubstituteGroups(finalResults || 0);
    };
    liftFinalData();
  }, [sendPressed, finalGroups, wait]);
英文:

I think the way my code is behaving at the present moment it seems that prepareList doesn't update in time and thus is undefined and then code gives an error saying filter is not a function, and it returns finalGroups as it should if there is no prepareList.length. I'm certain that the map inside prepareList itself works and there are values (array of objects) behind removedSubstitutesList which itself is useState array.

As you can see I've tried to prevent this behavior by adding completely irrelevant useEffect and makeWay and by doing setWait inside of it just to make it wait a bit longer to be able to get values to prepareList. Also dependencylists are part of trying to get it working somehow to see what is wrong.

My question is: is my reduce function itself wrong and thus it doesn't work or if it is indeed the problem of useState, multiple renderings etc. so that reducer function runs too early without a value or is there something else that I haven't noticed.

This code is a part of a bigger set and this part is supposed to gather, process and lift up prepared data to the main app component for it to use. Sendpressed here is a buttonclick and liftSubstitutes and liftSubstituteGroups are callbacks to send data to main app component.

Hopefully I've managed to be clear enough to follow through and if not I'll try my best to guide you through it. Any suggestions are welcomed, thanks in advance.

 useEffect(() => {
    const makeWay = () => {
      setWait('a');
    };
    makeWay();
  }, [sendPressed, finalGroups, removedSubstitutesList]);

  useEffect(() => {
    const liftFinalData = () => {
      const prepareList = removedSubstitutesList.map(item => item.email);
      const finalResults = !prepareList.length
        ? finalGroups
        : prepareList.reduce(
            (results, filter) => results.filter(filter),
            finalGroups[0].data
          );

      liftSubstitutes(Substitutes || 0);
      liftSubstituteGroups(finalResults || 0);
    };
    liftFinalData();
  }, [sendPressed, finalGroups, wait]);

答案1

得分: 0

你的假设是正确的,问题出在reduce()中的filter()

所以Array.prototype.reduce()接受两个参数:

  1. 第一个是累加器,在你的情况下是finalGroups[0].data,看起来没问题。
  2. 第二个是迭代中的当前值 - filter 变量。

所以在你的情况下,我猜问题在于如错误消息所述,filter 不是一个函数。从技术上讲,在这种情况下,filter 是来自 prepareList 数组的一个元素。

对于 Array.prototype.filter(),你需要传递一个返回 truefalse 值的函数,根据提供的函数来实现测试的元素将创建一个新数组。

考虑以下解决方案:

(results, prepareListElem) => results.filter(element => {
   var passTest = false;

   // 实现 passTest 的逻辑

   return passTest;
})

提供一个可以工作的示例来说明reduce()filter()的工作方式:

const array = [{name: 'John'}, {name: 'Jane'}];
const result = array.reduce((acc, cur) => {
   acc.push({
      ...cur,
      age: 12
   });

   return acc;
}, []);

console.log(result);

const filtered = result.filter(e => e.name.indexOf('a') !== -1);

console.log(filtered);

在我的示例中,我们有一个包含所有对象都具有 name 属性的数组。我们试图扩展它们的 age 属性。最后,我们通过筛选 name 属性包含字符 a 的对象来进行过滤。

希望这有助于解决你遇到的问题并澄清了问题所在!

英文:

Your assumption is correct, the issue is with filter() in reduce().

So Array.prototype.reduce() takes 2 arguments:

  1. The first is the accumulator, in your case finalGroups[0].data which looks okay.
  2. The second is the current value from the iteration - filter variable.

So in your case I guess the issue is that as the error message states that filter is not a function. Technically filter in this case one element from prepareList array.

For Array.prototype.filter() you need to pass a function which return true or false value, from the documentation:

> The filter() method creates a new array with all elements that pass the test implemented by the provided function.

Think about the following solution:

(results, prepareListElem) => results.filter(element => {
   var passTest = false;

   // the logic to implement for passTest

   return passTest;
})

Giving one working example how reduce() and filter() are working:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const array = [{name: &#39;John&#39;}, {name: &#39;Jane&#39;}];
const result = array.reduce((acc, cur) =&gt; {
   acc.push({
      ...cur,
      age: 12
   });

   return acc;
}, []);

console.log(result);

const filtered = result.filter(e =&gt; e.name.indexOf(&#39;a&#39;) !== -1);

console.log(filtered);

<!-- end snippet -->

In my example, we have elements in an array where all the object has name property. We are trying to extend with age. At the end we are filtering where the name property contains character a.

I hope this helps and clarifies where you have issues!

huangapple
  • 本文由 发表于 2020年1月6日 02:30:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/59602969.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定