Besoin d'une suggestion pour avoir une fonction dans un composant fonctionnel dans react Hooks
.
Pour autant que j'ai fait des recherches, beaucoup disent que c'est une mauvaise pratique car cela crée une fonction imbriquée/intérieure chaque fois que nous appelons un nouveau rendu. Après avoir fait une analyse,
J'ai trouvé que nous pouvons utiliser onClick={handleClick.bind(null, props)}
sur l'élément et placer la fonction en dehors du composant fonctionnel.
Exemple:
const HelloWorld = () => {
function handleClick = (event) => {
console.log(event.target.value);
}
return() {
<>
<input type="text" onChange={handleClick}/>
</>
}
}
Veuillez indiquer s'il existe un autre moyen.
Merci d'avance.
Ne vous inquiétez pas de créer de nouvelles fonctions sur chaque rendu. Ce n'est que dans les cas Edge que cela entrave vos performances. Les gestionnaires onClick
ne sont pas de ceux-là, alors créez simplement une nouvelle fonction sur chaque rendu.
Cependant, lorsque vous devez vous assurer que vous utilisez la même fonction à chaque fois, vous pouvez utiliser seCallaback
useCallback
pour onClick
Voici une raison pour laquelle vous ne devriez pas vous embêter avec les gestionnaires useCallback
pour onClick
(et la plupart des autres gestionnaires d'événements).
Considérez les extraits de code suivants, un sans useCallback:
function Comp(props) {
return <button onClick={() => console.log("clicked", props.foo)}>Text</Button>
}
et un avec useCallback:
function Comp(props) {
const onClick = useCallback(() => {
console.log("clicked", props.foo)
}, [props.foo])
return <button onClick={onClick}>Text</Button>
}
La seule différence dans ce dernier est que React doen doit changer le onClick
sur votre bouton si props.foo
reste le même. Changer le rappel est une opération très bon marché , et cela ne vaut pas la peine de compliquer votre code pour l'amélioration théorique des performances qu'il donne.
En outre, il convient de noter que une nouvelle fonction est toujours créée sur chaque rendu même lorsque vous utilisez useCallback
, mais useCallback
renverra l'ancien tant que les dépendances passées comme second argument ne seront pas modifiées.
useCallback
Le point d'utilisation de useCallback
est que si vous comparez deux fonctions avec l'égalité de référence, fn === fn2
n'est vrai que si fn
et fn2
pointe vers la même fonction en mémoire. Peu importe si les fonctions faites les mêmes.
Ainsi, si vous avez une mémoisation ou si vous n'exécutez du code que lorsque la fonction change, il peut être utile d'utiliser useCallback
pour réutiliser la même fonction.
Par exemple, React les hooks comparent les anciennes et les nouvelles dépendances, probablement en utilisant Object.is .
Un autre exemple est React.PureComponent , qui ne sera rendu que lorsque les accessoires ou l'état auront changé. Cela peut être utile pour les composants qui utilisent beaucoup de ressources pour le rendu. Passer par exemple un nouveau onClick
vers un PureComponent sur chaque rendu entraînera un nouveau rendu à chaque fois.
Vous pouvez utiliser la fonction useCallback
:
const HelloWorld = ({ dispatch }) => {
const handleClick = useCallback((event) => {
dispatch(() => {console.log(event.target.value)}0;
})
return() {
<>
<input type="name" onChange={handleClick}/>
</>
}
}
useCallback
renverra une version mémorisée du rappel qui ne change que si l'une des dépendances a changé. Ceci est utile lors du passage de rappels à des composants enfants optimisés qui s'appuient sur l'égalité de référence pour éviter des rendus inutiles (par exemple, shouldComponentUpdate).
Pour plus de détails, visitez leur lien de référence: React useCallback
L'ancienne méthode a également deux options.
Première solution: passer la fonction votre handleClick
à votre composant fonctionnel.
const HelloWorld = (props) => {
return() {
<>
<input type="name" onChange={props.handleClick}/>
</>
}
}
Deuxième solution: définir votre fonction en dehors de votre composant fonctionnel.
beaucoup disent que c'est une mauvaise pratique car cela crée une fonction imbriquée/intérieure à chaque fois que nous appelons un nouveau rendu
Non, les fonctions/fermetures internes sont si courantes qu'elles ne posent aucun problème. Le moteur peut fortement les optimiser.
Le point ici est que vous passez la fonction comme accessoire au composant enfant. Et comme la fonction a été "recréée", elle n'est pas équivalente à la fonction précédente passée, et donc l'enfant fait un nouveau rend (et c'est mauvais pour les performances).
Vous pouvez résoudre ce problème avec useCallback
, qui mémorise la référence de la fonction.
Selon React Documentation (fin de la partie),
Le problème avec cette dernière syntaxe est qu'un rappel différent est créé à chaque rendu de
LoggingButton
. Dans la plupart des cas, c'est très bien. Cependant, si ce rappel est passé en tant qu'accessoire aux composants inférieurs, ces composants peuvent effectuer un nouveau rendu supplémentaire. Nous recommandons généralement la liaison dans le constructeur ou l'utilisation de la syntaxe des champs de classe, pour éviter ce type de problème de performances.
Syntaxe des champs de classe:
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
fonction flèche dans la syntaxe de rappel:
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}