Функция стрелки в рендере Vs. атрибут для переноса данных - PullRequest
0 голосов
/ 17 марта 2020

Разрабатывая в REACT, я несколько раз сталкивался с необходимостью передачи элемента в функцию, например, так:

// Inside a Hook component
return (
  ...
  {nodes.map(n => <Node data={node} onClick={(e) => handleNodeClick(e, node)} />)}
);

В принципе, у меня есть переменная nodes, которая может прийти от props, useMemo, ... ничего. Затем я создаю <Node> компонент для каждого узла.
Наконец, как вы можете видеть, <Node> компонент имеет onClick реквизита, которые запускают функцию. В этой функции мне нужен узел со всеми его данными (представьте себе узел дерева с уникальным идентификатором, иконкой, ...).

Итак, записывая, как в примере, я добиваюсь того, что мне нужно , НО! У меня есть функция со стрелкой в ​​операторе return, и я также прочитал, что не хорошо иметь функцию со стрелкой в ​​методе render(). И я думаю, то же самое относится и к оператору return внутри компонента Hook.

Таким образом, чтобы преодолеть использование функции стрелки, я несколько раз использовал атрибут, чтобы избежать этого. По сути, что-то вроде этого:

// Inside a Hook component
const handleNodeClick = (e) => {
  if (e.target instanceof HTMLElement) {
    const nodeDOM = e.target.closest('[data-is-node]');

    if (nodeDOM) {
      const nodeIndex = e.target.getAttribute("data-node-index");
      const node = nodes[nodeIndex];

      ...
    }
  }
}

return (
  ...
  {nodes.map((n, i) => <Node
    data={node}
    data-is-node={''}
    data-node-index={i}
    onClick={handleNodeClick2} />)}
);

Итак, как вы можете видеть, в конце концов, в handleNodeClick2 у меня есть node, в котором я нуждаюсь. Но мне интересно, стоит ли всего лишь то, что мне нужно, или мне просто нужно использовать функцию стрелки.

Надеюсь, я достаточно хорошо объяснил вопрос. В частности, я даже не уверен, применима ли фраза «без функции стрелки внутри render() метода» также к компоненту Hook.

1 Ответ

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

Если вы хотите простоту функции со стрелкой без сложности, которую вы пытались, вы можете создать функцию более высокого порядка, которая принимает node, который вы хотите передать обратному вызову, и возвращает обратный вызов function.

// Higher Order Function to enclose `node` in function scope to be used later
// Function takes a node parameter and returns an event handler function
const handleNodeClick = node => e => {
  // node in function scope
  // do what you need
  ...
}

return (
  ...
  {nodes.map((node, i) => (
    <Node
      data={node}
      data-is-node={""}
      data-node-index={i}
      onClick={handleNodeClick2(node)}
    />
  ))}
);

Анонимные функции внутренних стрелок обычно идеально подходят для использования в функции рендеринга. Причиной того, что это иногда не рекомендуется, являются случаи, когда вы по существу передаете один и тот же обратный вызов реализацию группе отображаемых элементов, каждый отображенный элемент get является полной копией функции. Создание и создание всех этих функций обратного вызова может быть не дорогостоящим, но с этим связаны затраты. В подобных случаях шаблон должен просто определить именованный обратный вызов функции стрелки (один раз) и передать ссылку на него.

items.map(item => <button onClick={e => { /* expensive callback code */}}>{item}</button>)

против

const expensiveCallback = e => { /* expensive callback code */};

...

items.map(item => <button onClick={expensiveCallback}>{item}</button>)

Вы можете сделать это шаг далее, если вы обеспокоены и учитываете обратный вызов карты тоже

const expensiveCallback = e => { /* expensive callback code */};
const renderItemButton = item => <button onClick={expensiveCallback}>{item}</button>;

...

items.map(renderItemButton)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...