Задать вопрос
tsepen
@tsepen
Frontend developer

Передача анонимной функции в компонент?

Законен ли такой способ передачи функции, как я понимаю он замедляет производительность из за создания новой функции на каждом рендере, но на сколько это реально заметно?

<Input
     onChange={(e) =>
       dispatch(changeOrder({ ...order, building: e.target.value }))
     }
    value={order.building}
 />
  • Вопрос задан
  • 174 просмотра
Подписаться 2 Простой 2 комментария
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Помимо создания функции, которое само по себе не такая затратная операция, в компонент каждую перерисовку будет приходить новая ссылка, что при сравнении свойств вызовет его обновление.
Читаемость кода с таким подходом так же хуже.

Определяйте хандлеры в классовых компонентах свойствами класса, а в функциональных используйте хук useCallback.

Реальную разницу в производительности вы можете замерить с помощью бенчмарков и вкладок Performance и React Profiler в Dev Tools.

Что касается хранения состояния форм в redux, то в большинстве случаев в этом нет необходимости.

Насколько я понял, вы хотите использовать анонимные функции, потому что у вас возникли проблемы с определением имени обновляемого свойства в колбеке. Решение этой задачи:
const Example = () => {
  const [order, setOrder] = useState({
    building: '',
    otherProp: '',
  });

  const handleChange = useCallback(e => {
    const { name, value } = e.target;
    setOrder(s => ({ ...s, [name]: value }));
  }, []);

  return (
    <Input
      name="building"
      onChange={handleChange}
      value={order.building}
    />
  );
};

Версия с redux

Меняем редьюсер так, чтобы по действию updateOrder он принимал только измененные свойства и подмешивал их к старому значению order. Это позволит не добавлять зависимость в useCallback, да и вообще более правильное решение.
const Example = () => {
  const dispatch = useDispatch();
  const order = useSelector(orderSelector);

  const handleChange = useCallback(e => {
    const { name, value } = e.target;
    dispatch(updateOrder({ [name]: value }));
  }, []);

  return (
    <Input
      name="building"
      onChange={handleChange}
      value={order.building}
    />
  );
};

Этот прием описан в документации:
Обработка нескольких полей ввода
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Dasslier
FrontEnd Developer
Это обычная реализация обработчика события, с чего вы взяли, что это замедлит производительность? Или у вас множество таких обработчиков в этом компоненте?
Ответ написан
Комментировать
@camelCaseVlad
Две копейки от себя. По моему мнению, написанная вами функция в правильном исполнении должна выглядеть следующим образом:

const YourComponent = ({ changeOrder }) => (
   <Input
     onChange={(event) => changeOrder(prop1, event)
     // остальной код
 />
)

const mapStateToProps = () => {
  return {
    // нужный стейт
  }
} 

const mapDispatchToProps = (dispatch) => {
  return {
    changeOrder = (prop1, prop2) => dispatch(changeOrder(prop1, prop2)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(YourComponent);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы