如何将现有的 useEffect 重构为 useMemo 挂钩来过滤颜色数组?

问题描述 投票:0回答:1

我使用了两个状态变量来过滤颜色

search, resultantColors

现有的 useEffect 监视输入中的搜索,然后设置过滤后的数组。但是这些效果会在每次输入更改时运行,我如何才能将 useEffect 重构为 useMemo,以便能够减少重新渲染?

另外,useMemo 是否支持 componentDidMount(空数组依赖)、componentWillUnmount 的所有生命周期方法,因为我们想重构现有的 useEffect(组件 DidUpdate 生命周期)? - 可以对此给出是或否。

现场演示

我尝试减少重新渲染,但对于这个示例,useEffect 会在每次更改时运行,每次都会触发。另外,useMemo 是否处理 useEffect 的所有等效生命周期?

import { useEffect, useState } from 'react';

function App() {
  const mockColors = ['white', 'blue', 'yellow', 'green', 'orange', 'purple'];

  const [search, setSearch] = useState('');
  const [resultantColors, setResultantColors] = useState(mockColors);

  const handleInputChange = (e) => {
    setSearch(e.target.value);
  };

  useEffect(() => {
    if (search == '') {
      setResultantColors(mockColors);
    } else {
      const resultColors = resultantColors.filter((color) =>
        color.toLowerCase().includes(search.toLowerCase())
      );
      setResultantColors(resultColors);
    }
  }, [search]);

  return (
    <div style={{ border: '1px solid blue', padding: 20, margin: 20 }}>
      Filter Example with UseEffect <br />
      <label htmlFor="colors">Filter Color:</label>
      <input
        type="search"
        name="search"
        value={search}
        id="colors"
        onChange={(e) => {
          handleInputChange(e);
        }}
        placeholder="filter colors"
      />
      {resultantColors.length > 0 ? (
        resultantColors.map((value, index) => (
          <>
            <li key={`${value} + ${index}`}>{value}</li>
          </>
        ))
      ) : (
        <p>No items - search existing value </p>
      )}
    </div>
  );
}

export default App;


reactjs react-hooks
1个回答
0
投票

去掉

resultantColors
状态,每当
search
变化时就计算:

const { useMemo, useState } = React;

const mockColors = ['white', 'blue', 'yellow', 'green', 'orange', 'purple'];

function App() {
  const [search, setSearch] = useState('');

  const handleInputChange = (e) => {
    setSearch(e.target.value);
  };
  
  const resultantColors = useMemo(() => 
    search == ''
    ? mockColors
    : mockColors.filter(color =>
      color.toLowerCase().includes(search.toLowerCase())
    )
  , [search]);

  return (
    <div style={{ border: '1px solid blue', padding: 20, margin: 20 }}>
      Filter Example with UseEffect <br />
      <label htmlFor="colors">Filter Color:</label>
      <input
        type="search"
        name="search"
        value={search}
        id="colors"
        onChange={handleInputChange}
        placeholder="filter colors"
      />
      {resultantColors.length > 0 ? (
        resultantColors.map((value, index) => (
          <>
            <li key={`${value} + ${index}`}>{value}</li>
          </>
        ))
      ) : (
        <p>No items - search existing value </p>
      )}
    </div>
  );
}

ReactDOM
  .createRoot(root)
  .render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>

<div id="root"></div>

© www.soinside.com 2019 - 2024. All rights reserved.