В дополнение ко всем людям, указывающим, что +
перегружен для строк, -
также перегружен для операций с плавающей запятой и целыми числами, как и *
и /
.
[edit] %
также перегружен для плавающей запятой, что может быть неожиданностью для тех, у кого есть фон C или C ++.
При использовании перехватчиков вы должны соблюдать определенные правила перехвата (на данный момент их всего два):
Пытаясь передать ловушку обычной функции , вы нарушаете обе из них . И хотя эти правила являются скорее соглашениями, чем фактическими ограничениями и могут работать (, как другие в этой теме упоминали ), в некоторых случаях ( либо вы знаете, где и почему вы можете их использовать, либо вы случайно) удовлетворяя требованиям их использования ) , не рекомендуется использовать их таким образом. Например, через некоторое время вы можете забыть, что ваша функция содержит хук и фактически зависит от того, где и как она объявлена и используется, и переместить ее или поставить в условную, эффективно нарушающую логику вашего приложения.
Очень важно, чтобы ребята из React придумали специальный плагин ESlint , который предназначен для анализа вашего кода в фоновом режиме и точного предупреждения, когда вы близки к нарушению правил хуков. Это способ узнать наверняка.
Если вам все еще нужно извлечь некоторую зависимую от перехвата логику из вашего компонента в отдельную функцию, рассмотрите возможность создания пользовательского перехватчика .
НО!
В вашем примере кода вы не передаете функцию функции. React.useState
- это хук, но возвращаемое им setX
- нет. Вы можете передать его так, как вам нравится, и вы на самом деле должны передать его вашим обычным функциям или пользовательским хукам!
Как гласит правило, хуки могут вызываться только в верхней части функционального компонента и не должны вызываться условно, поэтому, хотя технически вы можете передать его в качестве аргумента функции, но тогда вам нужно будет выполнить работать сразу
Так что
const App = () => {
const [X, setX] = React.useState('x');
function Y(useX){
useX('string');
}
Y(React.useState);
return <div>Hello {X}</div>
}
ReactDOM.render(<App/>, document.getElementById('app'));
<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="app" />
будет в порядке.
Но приведенный ниже код не будет работать
const App = () => {
const [X, setX] = React.useState('x');
function Y(useX){
useX('string');
}
return <div>Hello {X} <button onClick={() => {Y(React.useState)}}>Click</button></div>
}
ReactDOM.render(<App/>, document.getElementById('app'));
<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="app" />
Следовательно, вы не должны использовать его таким образом, потому что он может случиться так, что вы позже добавите некоторые операторы в вызовы функций, и, следовательно, ловушка не сохраняет порядок своего вызова
Требуется поддержание порядка вызова Hooks, поскольку React полагается на порядок вызовов ловушек для поддержания очереди перехватчики используются в методе и обрабатывают все дальнейшие обновления ] blockquote>
В этом случае передается не функция ловушки, а функция установки, ограничения ловушки не применимы к Y(setX)
. Он не обязательно должен находиться в области действия компонента:
function Y(setX){
setX('string');
}
const Comp = () => {
const [X, setX] = useState('');
Y(setX);
...
}
В зависимости от использования он может извлечь выгоду из запоминания, например, если () => Y(setX)
следует передать как реквизит:
const Comp = () => {
const [X, setX] = useState('');
const setY = useCallback(() => Y(setX), []);
...
}