reactjs 避免在Render函数中定义内联函数

4urapxun  于 2022-12-22  发布在  React
关注(0)|答案(3)|浏览(174)

我看过很多文章说在react的render函数中定义内联函数会导致性能问题。
因此,他们建议在渲染函数之外定义函数,并在我需要的地方使用它(onClick等)。
我建立了一个示例代码,我有一个按钮列表,每个按钮将增加列表中的索引状态,但其抛出错误。
如何在onClick中传递参数而不使用内联函数

const App = () => {
  const [number, setNumber] = useState(1);
  const increaseNumber = (num) => {
    setNumber((prevState) => prevState + num);
  };
  return (
    <div>
      {[...Array(5)].map((item, index) => (
        <button key={index} onClick={increaseNumber(index)}>
          {`increase by ${index}`}
        </button>
      ))}
      <div>{number}</div>
    </div>
  );
};
export default App;
zy1mlcev

zy1mlcev1#

在回答这个问题之前,我会说,在尝试优化任何东西之前,您确实应该分析您的应用程序并确定特定的性能问题,在这种情况下,您可以使用data attributes来避免在每次Map迭代时创建新的回调。

function App() {
    const [number, setNumber] = useState(1);

    const increaseNumber = (event) => {
        const index = parseInt(event.target.dataset.index);
        setNumber((prevState) => prevState + index);
    };

    return (
        <div>
            {[...Array(5)].map((item, index) => (
                <button key={index} onClick={increaseNumber} data-index={index}>
                    {`increase by ${index}`}
                </button>
            ))}
            <div>{number}</div>
        </div>
    );
}

export default App;

通常情况下,只有当回调被用作子组件中的 prop 时,才需要为每个呈现创建一个新的回调。在这种情况下,使用类似useCallback的东西可以帮助避免不必要的子呈现。

tgabmvqs

tgabmvqs2#

方法1:使用备忘录

当参数是固定的,就像你的情况一样,你可以使用useMemo

import { useMemo, useState } from "react";

const indexes = [...Array(5)].map((_item, idx) => idx);

const App = () => {
    const [number, setNumber] = useState(1);

    const increaseNumber = useMemo(() => {
        return indexes.map(index => () => setNumber(prevNumber => prevNumber + index));
    }, [indexes]);

    return (
        <div>
            {indexes.map(index => (
                <button key={index} onClick={increaseNumber[index]}>
                    increase by {index}
                </button>
            ))}

            <div>{number}</div>
        </div>
    );
};

方法二: Package 器组件+ useCallback

创建自己的按钮组件并传递索引:

const IncreaseButton = ({ setNumber, index }) => {
    const increaseByIndex = useCallback(() => {
        return setNumber(prevValue => prevValue + index);
    }, [setNumber, index]);

    return <button onClick={increaseByIndex}>increase by {index}</button>;
};
yzuktlbb

yzuktlbb3#

您可以将一个项目作为已记忆的函数传递给react按钮元素的onClick prop。

const App = () => {
  const [number, setNumber] = useState(1);
  const increaseNumber = (num) => () => {
    setNumber((prevState) => prevState + num);
  };

  const btns = useMemo(() => {
    // here I am using lodash memoize function you may use your own
    let inc = _.memoize(increaseNumber)
    return Array(500).fill(0).map((_, index) => inc(index))
  }, [])
  return (
    <div>
      {btns.map((item, index) => (
        <button key={index} onClick={item}>
          {`increase by ${index}`}
        </button>
      ))}
      <div>{number}</div>
    </div>
  );
};

相关问题