如何使用 Hooks API 在 React 中避免不必要的渲染

Cas*_*raH 2 reactjs react-dom react-hooks usecallback

请跟随我的代码段下面,当我点击任何按钮(添加,编辑,删除)我所有的部件得到重新渲染,包括Title它没有成分propsstats。如果我有几个组件可能没问题,但假设我有超过15 个或更多的组件来获取/保存数据,这是可以的还是应该避免?

我尝试使用useCallback钩子(使用handleRemove),但显然这不能按预期工作。

const Button = ({ title, count, onClick }) => {
  console.log(`Rendering ${title}`)
  return (
    <button onClick={onClick}>
      {title} ({count})
    </button>
  )
}
const Header = () => {
  console.log("Rendering Title")
  return <h1>App Title</h1>
}

const Parent = () => {
  const [add, setAdd] = React.useState(0)
  const [edit, setEdit] = React.useState(0)
  const [remove, setRemove] = React.useState(0)
  
  const handleAdd = () => setAdd(add + 1)
  const handleEdit = () => setEdit(edit + 1)
  const handleRemove = React.useCallback(() => {
    setRemove(remove + 1)
  }, [remove])

  return (
    <React.Fragment>
      <Header />
      <Button title="Add" onClick={handleAdd} count={add} />
      <Button title="Edit" onClick={handleEdit} count={edit} />
      <Button title="Remove" onClick={handleRemove} count={remove} />
    </React.Fragment>
  )
}

function App() {
  return (
    <div className="App">
      <Parent />
      <button onClick={console.clear}>Clear log</button>
    </div>
  )
}

ReactDOM.render( <App /> , document.getElementById('root'))
Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

mac*_*ost 6

评论和另一个答案中有一些更高级的信息,但我想解决一些关于 React 工作原理的更基本的问题,以及:

如果我有几个组件可能没问题,但假设我有超过 15 个或更多的组件来获取/保存数据,这是可以的还是应该避免?

在 React 中,即使一个组件被“重新渲染”......在它的函数被重复调用的意义上......它不会在最重要(即昂贵)的地方“重新渲染”:在实际DOM。或者更确切地说,除非函数返回不同的东西,否则它不会。

因此,每次您console.log在 React 组件中看到 a时,都只意味着涉及到虚拟DOM,因此这种更改的成本低得多(同样,假设您的组件不断返回相同的 JSX)。

现在当然任何函数调用仍然有成本,并且您希望最终最大限度地减少组件渲染的次数,但同时重要的是要记住著名程序员 Donald Knuth 的话:

过早优化是万恶之源

如果您甚至连最轻微的性能问题都没有看到,那么担心组件在虚拟 DOM 中渲染的确切次数会让您错过 React 的一些天才:您交易了大量的人类甚至无法观察到的用于“性能优化”的昂贵资源(您的想法)。

相反,您绝对想阅读有关该库的更多信息,了解是什么触发了渲染调用(本质上是 props/state/context 更改,但有重要的细节),并尝试以这种方式理解和提高性能。学习 React 中“升级”的所有内容。

但是,特别是如果你只是在学习这个库,你真的不需要担心重新渲染任何特定的组件几次,因为 React 的设计非常巧妙,让我们专注于我们的组件做什么,而不是确切地说它是如何完成的......或者至少大部分时间(我当然不想让它听起来像 React 是一个“神奇的性能子弹”)。