reactjs React在输入数据更改后仅部分重新呈现无状态组件

kknvjkwl  于 2023-06-22  发布在  React
关注(0)|答案(1)|浏览(91)

我有下面的示例react(v18.2)代码,它工作得很好,正如预期的那样->一旦searchParams中的p发生变化,MyComponent中的列表就会被新的数据替换。P随着用户在输入字段中的击键而改变。

const ParentComponent = ({ searchParams }) => {
  const generateData = (searchParams) => {
    const { p } = searchParams;
    const newData = [];

    for (let i = 0; i < 10; i++) {
      const newItem = p + i.toString();
      newData.push(newItem);
    }

    return newData;
  };

  const data = generateData(searchParams);

  return (
    <div>
      <MyComponent data={data} />
    </div>
  );
};

const MyComponent = ({ data }) => (
  <ul>
    {data.map(item => (
      <li key={item}>{item}</li>
    ))}
  </ul>
);

然而,在我的实际组件中,generateData函数由4个for循环组成,用于创建数据。4个for循环总共循环最多(5个选项 * 4个选项 * 2个选项 * 2个选项=)80次,以生成所需的数据,例如:如下:

for (let i = 0; i < 5; i++) {
 const newItem = p + i.toString()
  for (let j = 0; j < 4; j++) {
   newItem += j.toString()
    for (let k = 0; k < 2; k++) {
     newItem += k.toString()
      for (let l = 0; l < 2; l++) {
       newItem += l.toString()
       newData.push(newItem);
      }
    }
  }
}

我的问题

  • 如果我只在代码中添加第二个for循环(或者第三个、第四个循环,或者所有循环的组合),MyComponent中的列表不会被新数据替换,而是保留所有历史数据并将所有新数据追加到列表中。
    预期行为
  • MyComponent中的列表应该在新数据进入时替换旧数据,而不是将新数据追加到列表中。
    我尝试了什么
  • 删除for循环(使用1个for循环可以正常工作,添加第二个循环后会中断)
  • 减少for循环中的选项数量(没有帮助)
  • 在父级中引入useState(没有帮助)
  • 将generateData函数移到组件之外(没有帮助)
  • 询问ChatGPT(没有帮助-尽管它表明这可能是generateData函数中的性能问题。我可以想象,但不是用这么少量的循环-对吗?)

编辑:最小可重现的示例(我是一个初学者程序员-我不知道如何将nextjs片段添加到codepen或类似的代码-但这在我的本地主机上运行并重现错误。

'use client';

import { usePathname, useRouter } from 'next/navigation';

const generateData = (keywords: string[] = ['test', 'stack']) => {
  const newData = [];
  const minChunk = 2;
  const maxChunk = 3;

  for (let i = 0; i < keywords.length; i += 1) {
    const word = keywords[i];
    for (let j = 0; j < keywords.length; j += 1) {
      if (i !== j) {
        const nextWord = keywords[j];
        for (let k = minChunk; k < maxChunk + 1; k += 1) {
          const firstChunk = word.slice(0, k);
          for (let l = minChunk; l < maxChunk + 1; l += 1) {
            const nextChunk = nextWord.slice(-l);
            const newItem = firstChunk + nextChunk;
            newData.push(newItem);
          }
        }
      }
    }
  }

  return newData;
};

export default function ParentComponent({
  searchParams,
}: {
  searchParams: {
    p: string;
  };
}) {
  const keyword = searchParams.p ?? '';
  const keywordArray = keyword.split(',');
  const { replace } = useRouter();
  const pathname = usePathname();

  if (keywordArray[keywordArray.length - 1] === '') {
    keywordArray.pop();
  }

  const data = generateData(keywordArray);

  function handleChange(term: string, paramLetter: string) {
    const params = new URLSearchParams(window.location.search);
    if (term) {
      params.set(paramLetter, term);
    } else {
      params.delete(paramLetter);
    }

    replace(`${pathname}?${params.toString()}`);
  }

  return (
    <div className="container mt-32">
      <input
        id="keyword"
        placeholder="Keyword"
        onChange={(e) => handleChange(e.target.value.split(' ').join(','), 'p')}
      />

      <h1>Results: </h1>
      <ul>
        {data.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
}
i86rm4rw

i86rm4rw1#

你不能在常量上使用+=操作,因为它是一个重新赋值。这导致了一个错误,我的假设是您的HMR设置导致它看起来像是其他问题。
除此之外,你的循环工作如预期。

const ParentComponent = ({ searchParams }) => {
  const generateData = (searchParams) => {
    const { p } = searchParams;
    const newData = [];

    for (let i = 0; i < 5; i++) {
     let newItem = p + i.toString();
      for (let j = 0; j < 4; j++) {
       newItem += j.toString();
        for (let k = 0; k < 2; k++) {
         newItem += k.toString();
          for (let l = 0; l < 2; l++) {
           newItem += l.toString();
           newData.push(newItem);
          }
        }
      }
    }

    return newData;
  };

  const data = generateData(searchParams);

  return (
    <div>
      <MyComponent data={data} />
    </div>
  );
};

const MyComponent = ({ data }) => (
  <ul>
    {data.map(item => (
      <li key={item}>{item}</li>
    ))}
  </ul>
);

ReactDOM.render(<ParentComponent searchParams={{ p: 'test' }} />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />

相关问题