C'était un vendredi soir typique, qui s'est déroulé comme prévu. La dernière version de notre application React Native vient d'être mise en production via la Play Console, avec un déploiement contrôlé ciblant 30 % des utilisateurs. Cependant, notre sens de la routine a été brusquement brisé lorsqu'une alerte critique est apparue dans le tableau de bord de Google Analytics : le taux d'utilisateurs sans crash a chuté de 99 % à 92 %. Cette baisse alarmante a déclenché une situation code rouge.
Grâce à mon équipe incroyablement assidue, nous nous sommes immédiatement réunis pour un appel, même en pleine nuit. En tirant parti de l'outil Google Crash Analytics, nous avons analysé la trace de la pile et suivi le comportement des utilisateurs sur tous les écrans. Malgré ces informations, nous n’avons pas pu identifier un modèle cohérent permettant de reproduire le crash. La seule théorie plausible était qu'une déclaration de retour anticipé accidentelle dans le code pourrait en être la cause.
Trouver le bug
En l’absence de modèle perceptible dans le comportement des utilisateurs, nous nous sommes tournés vers la différence de version dans notre base de code. Méticuleusement, nous avons examiné chaque ligne de code et passé au peigne fin plus de 150 différences Git, à la recherche d'anomalies. Pourtant, l’insaisissable déclaration de retour anticipé n’a pas été détectée. Néanmoins, nous avons mis en œuvre une série d’optimisations et poussé une mise à jour en production. Même si l'accident s'est reproduit 12 heures plus tard, sa fréquence a considérablement diminué.
La percée est survenue de manière inattendue. Alors que je travaillais sur une fonctionnalité distincte, ma connexion Internet s'est brièvement déconnectée et l'application s'est avérée ouverte. À ma grande surprise, l’erreur fatale est apparue sous mes yeux.
L'erreur
const {isConnected} = netState(); if (!isConnected){ return; } const calculateMyView = useCallback(() => { // ...some code },[]);
Après un débogage approfondi, nous avons retracé le problème à une première instruction return enfouie profondément dans l'un de nos composants. Ce bug subtil introduisait un crash dans des circonstances spécifiques : lorsqu'un utilisateur se reconnectait à une connexion Internet stable, ce qui obligeait le composant à tenter un nouveau rendu.
Que se passe-t-il en interne ?
Rendu initial
Lors du rendu initial, React enregistre chaque hook (par exemple, useCallback) dans l'ordre exact dans lequel ils sont appelés. Les hooks sont stockés dans une liste interne, indexés par leur position dans l'arborescence des composants.
Rendu ultérieurs
Lors des nouveaux rendus, React s'attend à ce que les hooks soient appelés dans le même ordre et aux mêmes positions. Si cet ordre change — par exemple, en raison d'une instruction return précoce qui ignore l'exécution d'un hook — la liste interne devient mal alignée. React tente ensuite d'accéder à un hook (par exemple, en position 1) qui n'a pas été exécuté, ce qui entraîne une erreur.
Le crash, identifié comme com.facebook.react.common.JavascriptException, s'est produit parce que React rendait moins de hooks que prévu - un symptôme classique de saut de logique avec état en raison d'un retour anticipé mal placé. Ce comportement a violé les règles de hooks de React, qui exigent que l'ordre d'exécution des hooks reste cohérent d'un rendu à l'autre. Par conséquent, tout utilisateur disposant de cet écran sur sa pile rencontrerait un crash si la connexion Internet tombait.
Le correctif
const {isConnected} = netState(); if (!isConnected){ return; } const calculateMyView = useCallback(() => { // ...some code },[]);
Pour résoudre le problème, nous avons réorganisé la logique pour garantir que l'instruction return n'interrompt plus le flux d'exécution des hooks. En effectuant cet ajustement, nous avons adhéré aux principes déclaratifs de React, stabilisé le processus de rendu et éliminé le crash.
Cette expérience a été un puissant rappel de l'importance de suivre les règles de hook de React et d'éviter les retours conditionnels dans la logique de rendu. Ces principes sont essentiels pour maintenir l'intégrité et la stabilité des applications React.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!