Пользовательский хук вызывает низкую производительность, хотя оптимизация с помощью useCallback не будет отражать новое состояние - PullRequest
0 голосов
/ 10 мая 2019

Я проводил эксперимент с React Hooks и столкнулся с довольно большой проблемой бомбардировки.

Я пытаюсь создать пользовательскую ловушку состояния формы.Я создал очень очень упрощенную версию своей работы, просто чтобы продемонстрировать здесь проблему: https://repl.it/@kadoshms/useCallbackCapture

Сам код приведен здесь (Для простоты я сохранил весь код в одном и том жеосновной файл):

import React, { Component, useState, useCallback } from 'react';
import logo from './logo.svg';
import './App.css';

const myHook = (e) => {
  const [values, setValues] = useState({
    checked: []
  });

  const setFormValues = useCallback((e) => {
    // some logic 
    if (e.currentTarget.checked) {
      setValues({
        checked: [...values.checked, e.currentTarget.value] 
      });
    } else {
      setValues({
        checked: values.checked.filter(v => v !== e.currentTarget.value)
      });
    }
  }, []);

  return [values, setFormValues];
}

const checkboxes = Array.from({length: 222}, (v, k) => k+1); 

const Checkbox = (props) => (
  <input type="checkbox"
      name={props.name}
      value={props.value} 
      checked={props.checked} onChange={props.onChange} />
);

// Checkbox.whyDidYouRender = true;

const Form = () => {
  //
  const [formData, setFormData] = myHook();
  return (
    <form>
      {checkboxes.map((c) => <Checkbox name="foo" checked={formData['checked'].includes(c.toString())}
       key={`c-${c}`} 
      onChange={setFormData} value={c} />)}
    </form>
  );
  //
};

class App extends Component {
  render() {
    return (
      <div className="App">
        <Form />
      </div>
    );
  }
}

export default App;

Проблема в значительной степени очевидна в приведенном мною примере.Хук useCallback , вероятно, захватывает последнее состояние, из-за которого массив checked не обновляется.Добавление formData в качестве зависимости или, с другой стороны, удаление памятки исправит это.Хотя это может вызвать проблемы с производительностью, поскольку обработчик onChange закрывается при каждом рендеринге.

Моя цель - использовать хуки, но сохранять высокую производительность, поэтому каждый флажок должен обновляться, только если он проверено значение изменено.

Редактировать: Я могу исправить проблему с помощью пользовательского обратного вызова React.memo, похожего на shouldComponentUpdate, хотя я думаю, что он менее элегантен.

Возможно ли это?

Заранее спасибо.

1 Ответ

0 голосов
/ 10 мая 2019

После некоторого прочтения я обнаружил следующий раздел FAQ в официальных документах React: https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-because-of-creating-functions-in-render

TL: DR: Вместо использования useState я создал редуктор, используя useReducer ловушку, как указано в документации. Если кому-то будет интересно, я буду рад поделиться своим решением для конкретной проблемы выше.

...