Feliz: [<reactcomponent>] vs React.functionComponent dans React refresh</reactcomponent>

Créé le 25 nov. 2020  ·  10Commentaires  ·  Source: Zaid-Ajaj/Feliz

Salut l'ami,

en tant que développeur frontend naïf, je suis entré dans un comportement intéressant:

Sur la base de vos documents, je préfère utiliser React.functionComponent pour créer des composants car je peux également spécifier le nom du composant pour un meilleur débogage. Une chose drôle vient avec le rafraîchissement de réaction.

Un code comme celui-ci déclenche toujours le rechargement de la page complète lors de toute modification de code:

let subView = React.functionComponent("SubView", fun () ->
    Html.text "Hello from sub"
)

let topView = React.functionComponent("TopView", fun () ->
    Html.div [ Html.div "Hello from top"; subView () ]
)

image

Mais avoir un composant racine avec [<ReactComponent>] rendra toutes les actualisations fonctionnelles sans faire une actualisation complète.

let subView = React.functionComponent("SubView", fun () ->
    Html.text "Hello from sub"
)

[<ReactComponent>]
let topView () = Html.div [ Html.div "Hello from top"; subView () ]

Est-ce un bug? Est-ce un bug dans la fonctionnalité de cravate noire fantaisie? Tout est de ma faute parce que je ne comprends pas la différence entre l'attribut ReactComponent et la fonction React.functionComponent? 😄

Merci pour tout type d'aide pour mieux comprendre.

question

Commentaire le plus utile

Wow! Juste wow! Une personne stupide pose une question stupide et un gars intelligent répond avec trois feuilles A4 pleines d'informations et d'explications pertinentes. 🤯 Tu fais juste du rock, mec! Merci beaucoup! ❤️ Maintenant, je comprends et je vais commencer à utiliser Attribute à la place.

Est-il toujours recommandé de nommer les composants d'une manière ou d'une autre (comme nous l'avons fait en utilisant le premier paramètre de React.functionComponent ) ou ce n'est plus nécessaire pour l'approche attributaire?

Tous les 10 commentaires

L'attribut sera la voie à suivre dans le futur et est nécessaire pour que react-refresh fonctionne. Au moins, c'était comme ça, mais je pensais que @ Zaid-Ajaj avait réglé le problème pour qu'il n'y ait aucune différence?

Salut Roman,

C'est une très bonne question à laquelle il n'y a pas de réponse courte, nous y voilà.

Bien qu'une fois que j'aurai réglé mes problèmes Internet à la maison, je reprendrai la diffusion en continu où j'expliquerai cela dans des détails atroces 😁

Sur la base de vos documents, je préfère utiliser React.functionComponent pour créer des composants car je peux également spécifier le nom du composant pour un meilleur débogage. Une chose drôle vient avec le rafraîchissement de réaction.

Tout d'abord, je tiens à souligner que la documentation est dans un état de transition malheureux: fondamentalement obsolète avec le dernier Feliz et [<ReactComponent>] goodness jusqu'à ce que nous résolvions les problèmes de plugin du compilateur et que nous stabilisions l'AST utilisé par Fable . Ce que j'essaie de dire, c'est que les documents ne favorisent React.functionComponent et si vous utilisez Fable 3, vous devriez commencer à utiliser [<ReactComponent>] place.

Cela a à voir avec la façon dont le code Javascript est généré. Maintenant, considérez ce morceau de code React:

const App = ({ title }) => {
  return (
    <h1>{title}</h1>
  )
};

<App title="My React Application" />

Ce JS (qui est en fait JSX) se résume au code JS suivant

import { createElement } from 'react'

const App = ({ title }) => {
  return createElement("h1", null, title);
};

// <App /> compiles to a call to createElement
createElement(App, { title: "My React Application" })

Il est très important de noter que l' initialisation du composant App via <App ... /> est compilée en un appel à createElement depuis JS.

C'est important à cause de deux choses:

  • Il sépare la définition du composant de sa création
  • Cela permet à App d'être une valeur statique (l'identité est réservée dont React utilise)

Maintenant, la façon dont React.functionComponent est implémentée est "mauvaise" pour React car elle combine la définition et la création en une seule fois. Ce code F #

let app React.functionComponent("App", fun (props: {|  tite: string |}) -> Html.h1 props.title)

Est en quelque sorte équivalent à dire

let app = 
  let render(props: {|  tite: string |}) = 
    let renderFn props= Html.h1 props.title
    createElement(renderFn , props)
  render.displayName <- "App"
  render

Maintenant c'est "mauvais" parce que createElement rend un composant qui est défini dynamiquement à chaque appel et il mute le displayName de la fonction plutôt que d'utiliser le nom de la fonction lui-même.

Ce sucre de syntaxe utilisé par React.functionComponent n'affecte pas le comportement d'exécution de React et c'est pourquoi nous pouvons l'utiliser sans problème pour créer l'application React. Les problèmes commencent à disparaître lorsque l' OUTIL autour des applications React commence à analyser le code généré: webpack, babel, react-refresh sont tous des outils qui regardent le code généré, injectent de la magie ici et là pour rendre possible le remplacement de module à chaud mais avec React.functionComponent ce n'est pas possible car le code généré n'est pas conforme à la façon dont les applications React sont généralement construites lorsque vous écrivez JS et de nombreux outils autour de React font des hypothèses basées sur le fait que le code est écrit selon la norme Réagissez cela que généré par un outil.

La solution à ces problèmes arrive dans Fable 3 où nous sommes autorisés à personnaliser la compilation du code via des plugins de compilateur. Si vous considérez ce code F # Feliz dans Fable 3

[<ReactComponent>]
let app (title: string) = Html.h1 title 

app "My  React Application"

Ensuite, il compile jusqu'à l'équivalent de ce JS (pas exact car plus de magie)

const App = (props) { 
   const title = props.title
   return createElement("h1", null, title)
}

createElement(App, { title: "My  React Application" })

Maintenant, ce code généré est personnalisé pour ressembler à ce que l'outillage React attend:

  • Les définitions et les créations des composants fonctionnels sont séparées
  • Les composants sont définis en majuscules (oui, cela est également requis et le plugin du compilateur réécrit automatiquement la définition)
  • Les paramètres d'entrée sont automatiquement traduits en accessoires React

Cette combinaison fait fonctionner le rafraîchissement de React et, par extension, rend l'expérience de Feliz très proche de celle du JS ou TS natif. J'espère que cela dissipe la confusion. Si vous avez d'autres questions, faites-le moi savoir 😉

Wow! Juste wow! Une personne stupide pose une question stupide et un gars intelligent répond avec trois feuilles A4 pleines d'informations et d'explications pertinentes. 🤯 Tu fais juste du rock, mec! Merci beaucoup! ❤️ Maintenant, je comprends et je vais commencer à utiliser Attribute à la place.

Est-il toujours recommandé de nommer les composants d'une manière ou d'une autre (comme nous l'avons fait en utilisant le premier paramètre de React.functionComponent ) ou ce n'est plus nécessaire pour l'approche attributaire?

Maintenant, je comprends et je vais commencer à utiliser Attribute à la place.

Impressionnant! Permettez-moi si vous rencontrez un problème 😉 pour le moment, le seul problème à prendre en compte est l'utilisation d'un type d' enregistrement comme accessoires d'entrée sera juste un peu problématique pour React-refresh, vous pouvez donc utiliser un enregistrement anonyme à la place ou des paramètres primitifs. J'espère que le problème sera bientôt résolu afin que je puisse documenter [<ReactComponent>] sans avoir aucune mise en garde.

Est-il toujours recommandé de nommer les composants d'une manière ou d'une autre (comme nous l'avons fait en utilisant le premier paramètre de React.functionComponent) ou ce n'est plus nécessaire pour l'approche attributaire?

Non, la seule exigence est que les composants soient compilés en majuscules, ce qui est l'une des choses que [<ReactComponent>] fait à la définition de la fonction: smile: vous pouvez l'implémentation ici

@Dzoukr la seule raison d'utiliser des noms pour vos composants de réaction est d'améliorer les outils de débogage.

@Shmew Yup, mais il n'y a pas de surcharge sur le constructeur ReactComponent pour l'ajout d'un tel nom, c'est pourquoi demandé.

Alors, continuez les questions [<ReactComponent>] vs functionComponent : hooks!

J'ai un composant qui doit initialiser un état. Heureusement, nous avons de nombreux hameçons fins disponibles! J'écris ceci:

[<ReactComponent>]
let Entrypoint() =
    let drawing, updateDrawing = React.useState(Deferred.HasNotStartedYet)
    let loader = React.useDeferredCallback((fun () -> loadDrawing()), updateDrawing)

    React.useEffect(loader, [||])
    // etc

Hélas, quand j'essaye d'exécuter ceci, ma console est triste et pleine d'erreurs:

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
    React 

J'ai suivi les étapes de débogage de réaction ci-dessus; aucun ne semble vrai. Cela devrait-il fonctionner? Est-ce une seule chose de Fable 3? (J'utilise toujours Fable 2.)

Je crois comprendre que l'attribut reactcomponent a besoin de fable 3 pour fonctionner car il s'agit d'un plugin de compilateur Fable 3

@landy ah, ça le ferait sûrement. Laisse-moi faire fonctionner Fable 3, je ferai un rapport dans une minute

Hey! Oui, cela m'a corrigé - j'ai utilisé ce PR comme guide pour la conversion.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

cmeeren picture cmeeren  ·  13Commentaires

Dzoukr picture Dzoukr  ·  6Commentaires

cmeeren picture cmeeren  ·  13Commentaires

alfonsogarciacaro picture alfonsogarciacaro  ·  11Commentaires

alfonsogarciacaro picture alfonsogarciacaro  ·  6Commentaires