Feliz: [<reactcomponent>] vs React.functionComponent na atualização React</reactcomponent>

Criado em 25 nov. 2020  ·  10Comentários  ·  Fonte: Zaid-Ajaj/Feliz

Olá amiga,

como ingênuo aspirante a dev frontend, comecei a ter um comportamento interessante:

Com base em seus documentos, sou a favor de usar React.functionComponent para criar componentes porque também posso especificar o nome do componente para uma depuração melhor. Uma coisa engraçada vem com a atualização de reação.

Um código como este sempre aciona o recarregamento da página inteira ao fazer qualquer alteração no código:

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

Mas ter o componente raiz com [<ReactComponent>] fará com que toda a atualização funcione bem sem fazer uma atualização completa.

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

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

É um bug? É um bug no recurso de black tie aka chique? É tudo minha culpa porque não entendi a diferença entre o atributo ReactComponent e a função React.functionComponent? 😄

Obrigado por qualquer tipo de ajuda para entender melhor.

question

Comentários muito úteis

Uau! Apenas Uau! Pessoa tola faz perguntas estúpidas e cara inteligente responde com três folhas A4 cheias de informações e explicações relevantes. 🤯 Você simplesmente arrasa, cara! Muito obrigado! ❤️ Agora eu entendo e irei começar a usar o Attribute em seu lugar.

Ainda é recomendado nomear componentes de alguma forma (como fizemos usando o primeiro parâmetro de React.functionComponent ) ou isso não é mais necessário para abordagem de atributo?

Todos 10 comentários

O atributo será o caminho a seguir no futuro, e é necessário para que o react-refresh funcione. Pelo menos foi assim, mas pensei que @ Zaid-Ajaj resolveu isso para que não houvesse diferença?

Oi romano,

Esta é uma pergunta muito boa para a qual não há uma resposta curta. Aqui vamos nós.

Porém, assim que resolver meus problemas de Internet em casa, vou retomar a transmissão novamente, onde explicarei isso em detalhes dolorosos 😁

Com base em seus documentos, sou a favor de usar React.functionComponent para criar componentes porque também posso especificar o nome do componente para uma melhor depuração. Uma coisa engraçada vem com a atualização de reação.

Em primeiro lugar, quero salientar que a documentação está em um infeliz estado de transição: basicamente desatualizada com o último Feliz e [<ReactComponent>] goodness até que resolvamos os problemas do plugin do compilador e estabilizemos o AST usado pelo Fable . O que estou tentando dizer é que os documentos não favorecem React.functionComponent e se você estiver usando o Fable 3, deve começar a usar [<ReactComponent>] .

Isso tem a ver com a forma como o código Javascript é gerado. Agora considere esta parte do código React:

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

<App title="My React Application" />

Este JS (que na verdade é JSX) desugars para o seguinte código JS

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" })

É muito importante notar que a inicialização do componente App via <App ... /> é compilada para uma chamada para createElement do JS.

É importante por duas coisas:

  • Ele separa a definição do componente de sua criação
  • Ele permite que App seja um valor estático (a identidade é reservada, da qual o React faz uso)

Agora, a maneira React.functionComponent é implementado é "ruim" para React porque combina a definição e a criação de uma vez. Este código F #

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

É uma espécie de equivalente a dizer

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

Agora, isso é "ruim" porque createElement renderiza um componente que é definido dinamicamente em cada invocação e altera o displayName da função em vez de usar o próprio nome da função.

Esta sintaxe que o React.functionComponent emprega não afeta o comportamento do tempo de execução do React e é por isso que podemos usá-lo sem problemas para construir o aplicativo React. Os problemas começam a surgir quando o TOOLING em torno dos aplicativos React começa a analisar o código gerado: webpack, babel, react-refresh são todas ferramentas que procuram o código gerado, injetam alguma mágica aqui e ali para tornar possível a substituição de módulos quentes, mas com React.functionComponent não é possível porque o código gerado não está em conformidade com a forma como os aplicativos React são normalmente construídos quando você está escrevendo JS e muitas das ferramentas em torno do React fazem suposições baseadas no fato de que o código é escrito de acordo com o padrão Reaja ao que é gerado por uma ferramenta.

A solução para esses problemas está chegando no Fable 3, onde podemos personalizar a compilação do código por meio de plug-ins do compilador. Se você considerar este código F # Feliz no Fable 3

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

app "My  React Application"

Em seguida, ele compila para o equivalente a este JS (não exato porque mais mágica)

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

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

Agora, esse código gerado é personalizado para se parecer com o que a ferramenta React espera:

  • Definições e criações de componentes de função são separadas
  • Os componentes são definidos em maiúsculas (sim, isso também é necessário e o plug-in do compilador reescreve automaticamente a definição)
  • Os parâmetros de entrada são traduzidos automaticamente em adereços React

Esta combinação faz o React atualizar funcionar e, por extensão, torna a experiência de Feliz muito próxima da de JS ou TS nativos. Espero que isso esclareça a confusão. Se você tiver mais perguntas, me avise 😉

Uau! Apenas Uau! Pessoa tola faz perguntas estúpidas e cara inteligente responde com três folhas A4 cheias de informações e explicações relevantes. 🤯 Você simplesmente arrasa, cara! Muito obrigado! ❤️ Agora eu entendo e irei começar a usar o Attribute em seu lugar.

Ainda é recomendado nomear componentes de alguma forma (como fizemos usando o primeiro parâmetro de React.functionComponent ) ou isso não é mais necessário para abordagem de atributo?

Agora eu entendo e irei começar a usar o Attribute em seu lugar.

Impressionante! Deixe-me se você encontrar algum problema 😉 agora o único problema a ter em conta é o uso de um tipo de registro como adereços de entrada será um pouco problemático para React-refresh, então você pode usar um registro anônimo em vez de parâmetros primitivos. Espero que o problema seja corrigido em breve para que eu possa documentar [<ReactComponent>] sem quaisquer ressalvas.

Ainda é recomendado nomear componentes de alguma forma (como fizemos usando o primeiro parâmetro de React.functionComponent) ou isso não é mais necessário para abordagem de atributo?

Não, o único requisito é que os componentes sejam compilados como valores em maiúsculas, que é uma das coisas que [<ReactComponent>] faz para a definição da função: smile: você pode a implementação aqui

@Dzoukr a única razão para usar nomes para seus componentes de reação é tornar as ferramentas de depuração melhores.

@Shmew Sim, mas não há sobrecarga no construtor ReactComponent para adicionar esse nome, então é por isso que perguntado.

Portanto, continuando as perguntas de [<ReactComponent>] vs functionComponent : ganchos!

Eu tenho um componente que precisa inicializar algum estado. Felizmente, temos muitos ganchos finos disponíveis! Eu escrevo isto:

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

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

Quando tento executar isso, meu console fica triste e cheio de erros:

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 

Eu já passei pelas etapas de depuração de reação acima; nenhum parece ser verdadeiro. Isso deveria estar funcionando? Isso é apenas uma coisa do Fable 3? (Ainda estou usando o Fable 2.)

Meu entendimento é que o atributo reactcomponent precisa de fábula 3 para funcionar porque é um plugin de compilador de fábula 3

@landy ah, com certeza

Ei! Sim, isso me consertou - usei este PR como um guia para a conversão.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

heimeshoff picture heimeshoff  ·  6Comentários

cmeeren picture cmeeren  ·  13Comentários

alfonsogarciacaro picture alfonsogarciacaro  ·  6Comentários

cmeeren picture cmeeren  ·  4Comentários

Dzoukr picture Dzoukr  ·  6Comentários