2

请按照下面的代码片段,当我单击任何按钮(添加、编辑、删除)时,我的所有组件都会重新渲染,包括Title没有props或的组件stats。如果我有几个组件可能没问题,但假设我有超过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'))
<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>

4

2 回答 2

6

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

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

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

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

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

过早优化是万恶之源

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

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

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

于 2020-04-08T01:20:33.003 回答
1

如果组件中的任何状态发生变化,它将被重新渲染。如果状态不打算在组件之间共享,请考虑将状态向下移动到按钮组件本身。这只会导致组件在被触发<AddButton/>时重新渲染。onClick

const AddButton = () => {
 const [add, setAdd] = React.useState(0)
 const handleAdd = () => setAdd(add + 1)

  return ( <Button title="Add" onClick={handleAdd} count={add} />)
 }
于 2020-03-22T23:04:37.450 回答