【问题标题】:Use spread operator to copy array state and add all objects that match使用扩展运算符复制数组状态并添加所有匹配的对象
【发布时间】:2020-07-06 15:59:23
【问题描述】:

我正在尝试将与正则表达式匹配的所有对象排序到一个数组中。 这似乎不适用于扩展运算符和 useState,有什么办法可以做到吗? 我现在得到的结果是样本只给了我最后一个匹配它的对象,没有别的。 我想要的效果是所有匹配的样本都被推入样本状态。

  const [accessories, setAccessories] = useState([]);
  const [paints, setPaints] = useState([]);
  const [samples, setSamples] = useState([]);

  // Load order into state
  useEffect(() => {
    loadUser();
    getOrderById(match.params.orderId);
  }, []);

  // Load order into state
  useEffect(() => {
    if (!loading) {
      console.log(order.line_items);
      for (let i = 0; i < order.line_items.length; i++) {
        if (order.line_items[i].sku.match(/^(TAC|T.BU.AC)/)) {
          console.log('SKU: ', order.line_items[i].sku);
          //@ts-ignore
          setAccessories([...accessories, order.line_items[i]]);
          console.log(accessories);
        }
        if (order.line_items[i].sku.startsWith('TBA') || order.line_items[i].sku.match(/^TCR(?!0000)/)
          || order.line_items[i].sku.match(/^TCR0000/)) {
          //@ts-ignore
          setPaints([...paints, order.line_items[i]]);
        }
        if (order.line_items[i].sku.match(/^TCR\d+P?\d+SAMP/)) {
          console.log(samples);
          console.log(order.line_items[i]);
          //@ts-ignore
          setSamples([...samples, ...[order.line_items[i]]]);
        }
      }
    }
  }, [loading]);

【问题讨论】:

  • order.line_items[i].sku.match(/^TCR(?!0000)/) || order.line_items[i].sku.match(/^TCR0000/) 没有意义 - 如果 sku 以 TCR 开头,则至少其中一个将评估为 true。您正在寻找与 0000 相关的逻辑是什么?

标签: javascript reactjs


【解决方案1】:

你在这里犯的错误很少。

错误一:

使用 for 循环在单个 useEffect 块内调用相同的 setStates 次数过多,这可能会极大地影响 React 的性能。同样,这显然违反了 Rules of HooksOnly Call Hooks at the Top Level

仅在顶层调用 Hooks

不要在循环、条件或嵌套函数中调用 Hooks。

错误2:

虽然这次没有之前的那么严重,但仍然是一个错误。不使用更好的解决方案,使用像 filter 这样的内置 JavaScript 方法,而不是编写自己的 for 循环

useEffect(() => {
  let _accessories;
  let _paints;
  let _samples;

  if (!loading) {
    _accessories = order.line_items.filter(({ sku }) => sku.match(/^(TAC|T.BU.AC)/))

    _paints = order.line_items.filter(({ sku }) => sku.startsWith('TBA') || sku.match(/^TCR(?!0000)|^TCR0000/))

    _samples = order.line_items.filter(({ sku }) => sku.match(/^TCR\d+P?\d+SAMP/))

    // Never use setState inside a for loop
  // of useEffects
  // Also avoid calling same setState multiple times

  // use callback setState if you want to access
  // previous state, but it ain't a compulsory like
  // for class components
  setAccessories(s => [ ...s, ..._accessories ])
  setPaints(s => [ ...s, ..._paints ])  
  setSamples(s => [ ...s, ..._samples ])
  } 

  // return in useEffect has different role
  // than normal functions

}, [loading])


【讨论】:

    【解决方案2】:

    将调用.filter 的结果传播到调用中:

    useEffect(() => {
      if (loading) {
        return;
      }
      const items = order.line_items;
      setAccessories([
        ...accessories,
        items.filter(({ sku }) => sku.match(/^(TAC|T.BU.AC)/))
      ]);
      setPaints([
        ...paints,
        items.filter(({ sku }) => sku.startsWith('TBA') || sku.match(/^TCR(?!0000)|^TCR0000/))
      ]);
      setSamples([
        ...samples,
        items.filter(item => item.sku.match(/^TCR\d+P?\d+SAMP/))
      ]);
    }, [loading]);
    

    【讨论】:

      猜你喜欢
      • 2021-03-16
      • 2019-09-01
      • 2017-09-26
      • 1970-01-01
      • 2018-05-13
      • 2017-06-28
      • 2017-03-17
      • 2018-03-31
      • 1970-01-01
      相关资源
      最近更新 更多