Реагируйте перехватывает useCallback с параметрами внутри цикла

Если вам нужно сделать sed на месте в сценарии bash, и вы НЕ хотите, чтобы на месте было результат с .bkp-файлами, и у вас есть способ обнаружить os (скажем, используя ostype.sh ), - тогда следующий хак с встроенной bash оболочкой eval должен работать:

OSTYPE="$(bash ostype.sh)"

cat > myfile.txt <<"EOF"
1111
2222
EOF

if [ "$OSTYPE" == "osx" ]; then
  ISED='-i ""'
else # $OSTYPE == linux64
  ISED='-i""'
fi

eval sed $ISED 's/2222/bbbb/g' myfile.txt
ls 
# GNU and OSX: still only myfile.txt there

cat myfile.txt
# GNU and OSX: both print:
# 1111
# bbbb

# NOTE: 
# if you just use `sed $ISED 's/2222/bbbb/g' myfile.txt` without `eval`,
# then you will get a backup file with quotations in the file name, 
# - that is, `myfile.txt""`

6
задан ApplePearPerson 5 March 2019 в 15:23
поделиться

1 ответ

Здесь простой ответ: вам, вероятно, не следует использовать useCallback здесь. Смысл useCallback состоит в том, чтобы передать один и тот же экземпляр функции оптимизированным компонентам (например, PureComponent или React.memo компонентам), чтобы избежать ненужных повторных отображений.

В этом случае вы не имеете дело с оптимизированными компонентами (или, как я подозреваю, в большинстве случаев), поэтому на самом деле нет причин запоминать обратные вызовы, как с useCallback.


Предположим, что запоминание важно, однако, лучшее решение здесь, вероятно, состоит в том, чтобы использовать одну функцию вместо пяти: вместо уникальной функции для каждой кнопки выполняется закрытие key, вы можете прикрепить [ 1112] к элементу:

<button data-key={key}>{key}</button>

А затем прочитайте ключ из event.target.dataset["key"] внутри обработчика одного клика:

const Example = (props) => {
  // Single callback, shared by all buttons
  const onClick = React.useCallback((e) => {
    // Check which button was clicked
    const key = e.target.dataset["key"]
    console.log("You clicked: ", key);
  }, [/* dependencies */]);
  
  return(
    <div>
      {
        _.times(5, (key) => {
          return (
            <button data-key={key} onClick={onClick}>
              {key}
            </button>
          );
        })
      }
    </div>
  );
};
console.log("hello there");

ReactDOM.render(<Example/>, document.getElementById('root'));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

<div id='root'>
</div>
[ 1129]


При всем этом можно запоминать несколько функций в одном хуке. useCallback(fn, deps) эквивалентно useMemo(() => fn, deps), а useMemo может использоваться для запоминания нескольких функций одновременно:

const clickHandlers = useMemo(() => _.times(5, key => 
  () => console.log("You clicked", key)
), [/* dependencies */]);

const Example = (props) => {
  const clickHandlers = React.useMemo(() => _.times(5, key => 
    () => console.log("You clicked", key)
  ), [/* dependencies */])
  
  return(
    <div>
      {
        _.times(5, (key) => {
          return (
            <button onClick={clickHandlers[key]}>
              {key}
            </button>
          );
        })
      }
    </div>
  );
};
console.log("hello there");

ReactDOM.render(<Example/>, document.getElementById('root'));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

<div id='root'>
</div>
[1119 ]

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

0
ответ дан Retsam 5 March 2019 в 15:23
поделиться
Другие вопросы по тегам:

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