Как избежать ненужного рендера в React с использованием Hooks API - PullRequest
1 голос
/ 23 марта 2020

Пожалуйста, следуйте приведенному ниже фрагменту кода. Когда я нажимаю любую кнопку (добавляю, редактирую, удаляю), все мои компоненты повторно визуализируются, включая компонент Title, который не имеет props или stats. Может быть хорошо, если у меня есть несколько компонентов, но давайте предположим, что у меня более 15 или больше с извлечением / сохранением данных, это OK или его следует избегать?

Я пытался использовать 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>

Ответы [ 2 ]

1 голос
/ 08 апреля 2020

В комментариях и в другом ответе есть более продвинутая информация, но я хотел бы рассказать немного подробнее о том, как работает React, и о:

Может быть, если я У меня примерно такое же количество компонентов, но давайте предположим, что у меня более 15 или более с извлечением / сохранением данных, это нормально или этого следует избегать?

В React, даже если компонент "повторно отображается «... в том смысле, что его функция вызывается неоднократно ... она не« перерисовывается »в самом важном (ie. дорогом) месте: в реальном DOM. Или, скорее, он не , если , если функция возвращает что-то другое.

Таким образом, каждый раз, когда вы видите console.log в компоненте React, он означает только виртуальный Был задействован DOM, и поэтому стоимость этого изменения на много, намного * на 1015 * ниже (опять же, при условии, что ваш компонент продолжает возвращать идентичный JSX).

Теперь, конечно, любой вызов функции по-прежнему имеет свою стоимость, и вы хотите в конечном итоге минимизировать количество раз, которое ваши компоненты визуализируют, но в то же время важно помнить слова известного программиста Дональда Кнута:

преждевременная оптимизация - это root всего зла

Если вы даже не видите ни малейшего намека на проблему с производительностью, то беспокойство о том, сколько раз компонент визуализируется в виртуальном DOM, заставляет вас упустить на некоторых из гений React: вы торгуете тоннами самого дорогого ресурса (ваше мышление) для «оптимизации производительности», которую даже человек не может наблюдать. * 1 024 *

Вместо этого вы абсолютно хотите больше узнать о библиотеке, понять, что запускает вызовы рендеринга (в основном изменяются реквизиты / состояние / контекст, но есть важные детали), и пытаетесь понять и улучшить производительность таким образом. Изучение всего, что является частью «прокачки» в React.

Но, особенно , если вы только изучаете библиотеку, вам действительно не нужно беспокоиться о повторном рендеринге. конкретный компонент несколько раз, потому что React был разработан очень умно, чтобы позволить нам сосредоточиться на том, что делают наши компоненты, а не на том, как это делается ... или, по крайней мере, большую часть времени (я, конечно, не хочу, чтобы это звучало например, React тоже «пуля производительности волхвов c».

1 голос
/ 23 марта 2020

Если какое-либо состояние изменяется в компоненте, он будет перерисован. Попробуйте переместить состояние вниз в сам компонент кнопки, если состояние не предназначено для совместного использования между компонентами. Это приведет только к тому, что компонент <AddButton/> будет перерисован при запуске onClick.

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

  return ( <Button title="Add" onClick={handleAdd} count={add} />)
 }
...