React 自定义钩子和 useMemo 钩子

fur*_*ceX 5 reactjs react-hooks react-usememo

我有两个“昂贵”的函数,我想在我的反应应用程序中记住它们,因为它们需要很长时间才能渲染。昂贵的函数用在数组映射中。我想记住数组映射的每个结果,这样如果数组的一个元素发生更改,只有该元素的昂贵函数将被重新计算。(并且要独立地记住昂贵的函数,因为有时只需要重新计算一个函数。)我正在努力解决如何记住并传递当前数组值的问题。

这是工作演示,没有记忆:

import React, { useMemo, useState } from "react";

const input = ["apple", "banana", "cherry", "durian", "elderberry", "apple"];

export default function App() {
  const output = input.map((msg, key) => createItem(msg, key));
  return <div className="App">{output}</div>;
}

const createItem = (message, key) => {   // expensive function 1
  console.log("in createItem:", key, message);

  return (
    <div key={key}>
      <strong>{"Message " + (1 + key)}: </strong>
      {message} =>{" "}
      <span
        id={"preview-" + key}
        dangerouslySetInnerHTML={{ __html: msgSub(message) }}
      />
    </div>
  );
};

const msgSub = message => {   // expensive function 2
  const messageSub = message.replace(/[a]/g, "A").replace(/[e]/g, "E");
  console.log("in msgSub:", message, messageSub);
  return messageSub;
};
Run Code Online (Sandbox Code Playgroud)

(我没有它在 SO 的编辑器上运行,所以在codesandbox上查看并运行它。)

这是我使用自定义挂钩和 useMemo 挂钩的尝试之一。

任何指导将不胜感激!

并为说明如何在 SO 编辑器中做出反应而加分!

HMR*_*HMR 0

使 item 成为纯组件:

const id = ((id) => () => id++)(1); //IIFE creating id
//pure component
const Item = React.memo(function Item({ increase, item }) {
  console.log('rendering id:', item.id);
  return (
    <ul>
      <button onClick={() => increase(item.id)}>
        {item.count}
      </button>
    </ul>
  );
});
const App = () => {
  const [items, setItems] = React.useState([]);
  //use callback, increase only created on app mount
  const increase = React.useCallback(
    (id) =>
      setItems((items) =>
        //use state setter callback
        //no dependencies for useCallback and no stale
        //closures
        items.map((item) =>
          item.id === id
            ? { ...item, count: item.count + 1 }
            : item
        )
      ),
    [] //no dependencies
  );
  return (
    <div>
      <div>
        <button
          onClick={() =>
            setItems((items) => [
              { id: id(), count: 0 },
              ...items,
            ])
          }
        >
          add counter
        </button>
      </div>
      <ul>
        {items.map((item) => (
          <Item
            key={item.id}
            item={item}
            increase={increase}
          />
        ))}
      </ul>
    </div>
  );
};
ReactDOM.render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)