Feliz: [<reactcomponent>] vs React.functionComponent в обновлении React</reactcomponent>

Созданный на 25 нояб. 2020  ·  10Комментарии  ·  Источник: Zaid-Ajaj/Feliz

Привет, друг,

как наивный подражатель фронтенд-разработчика, я обнаружил интересное поведение:

Основываясь на ваших документах, я предпочитаю использовать React.functionComponent для создания компонентов, потому что я также могу указать имя компонента для лучшей отладки. Забавная вещь идет с обновлением реакции.

Такой код всегда запускает полную перезагрузку страницы при любых изменениях кода:

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

Но наличие корневого компонента с [<ReactComponent>] заставит все обновления работать отлично, не выполняя полное обновление.

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

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

Это ошибка? Это ошибка в причудливом черном галстуке, также известном как особенность? Это все моя вина, потому что я не понимаю разницы между атрибутом ReactComponent и функцией React.functionComponent? 😄

Спасибо за любую помощь, чтобы лучше понять.

question

Самый полезный комментарий

Ух ты! Просто вау! Глупый человек задает глупый вопрос, а умный парень отвечает на трех листах формата А4, полных соответствующей информации и пояснений. 🤯 Ты просто молодец, мужик! Большое спасибо! ❤️ Теперь я понимаю и начну использовать Атрибуты.

По-прежнему рекомендуется как-то называть компоненты (как мы использовали первый параметр React.functionComponent ) или это больше не нужно для атрибутивного подхода?

Все 10 Комментарий

Атрибут будет использоваться в будущем и необходим для работы response-refresh. По крайней мере, так было, но я думал, что @ Zaid-Ajaj разобрался с этим, так что разницы не было?

Привет Роман,

Это действительно хороший вопрос, на который нет короткого ответа, вот и все.

Хотя, как только я решу свои проблемы с интернетом дома, я снова возобновлю потоковую передачу, где я объясню это в мучительных подробностях 😁

Основываясь на ваших документах, я предпочитаю использовать React.functionComponent для создания компонентов, потому что я также могу указать имя компонента для лучшей отладки. Забавная вещь идет с обновлением реакции.

Прежде всего, я хочу указать, что документация находится в неудачном переходном состоянии: в основном она устарела с последними версиями Feliz и [<ReactComponent>] goodness, пока мы не разберемся с проблемами плагина компилятора и не стабилизируем AST, используемый Fable. . Я пытаюсь сказать, что в документации не одобряется React.functionComponent и если вы используете Fable 3, вам следует вместо этого начать использовать [<ReactComponent>] .

Это связано с тем, как генерируется код Javascript. Теперь рассмотрим этот фрагмент кода React:

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

<App title="My React Application" />

Этот JS (который на самом деле является JSX) обессахаривается до следующего 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" })

Очень важно заметить, что инициализация компонента App через <App ... /> компилируется в вызов createElement из JS.

Это важно по двум причинам:

  • Он отделяет определение компонента от его создания.
  • Он позволяет App быть статическим значением (идентификатор зарезервирован, который использует React)

Теперь способ реализации React.functionComponent "плохой" для React, потому что он объединяет определение и создание за один раз. Этот код F #

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

Это что-то вроде того, что сказать

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

Теперь это «плохо», потому что createElement визуализирует компонент, который определяется динамически при каждом вызове, и изменяет displayName функции вместо использования самого имени функции.

Этот синтаксический сахар, который использует React.functionComponent , не влияет на поведение React во время выполнения, и именно поэтому мы можем использовать его без проблем для создания приложения React. Проблемы начинают выползать, когда ИНСТРУМЕНТ вокруг приложений React начинает анализировать сгенерированный код: webpack, babel, react-refresh - все инструменты, которые просматривают сгенерированный код, вводят некоторую магию здесь и там, чтобы сделать возможной замену горячего модуля, но с React.functionComponent это невозможно, потому что сгенерированный код не соответствует тому, как обычно создаются приложения React, когда вы пишете JS, и многие инструменты для React делают предположения, основанные на том факте, что код написан в соответствии со стандартом. Реагируйте на то, что генерируется инструментом.

Решение этих проблем находится в Fable 3, где нам разрешено настраивать компиляцию кода с помощью подключаемых модулей компилятора. Если вы рассмотрите этот код F # Feliz в Fable 3

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

app "My  React Application"

Затем он компилируется до эквивалента этого JS (неточно, потому что больше магии)

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

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

Теперь этот сгенерированный код настроен так, чтобы он выглядел так, как ожидает инструмент React:

  • Определения и создание функциональных компонентов разделены
  • Компоненты определены в верхнем регистре (да, это тоже необходимо, и плагин компилятора автоматически переписывает определение)
  • Входные параметры автоматически переводятся в реквизиты React

Эта комбинация заставляет React обновлять работу и, как следствие, делает Feliz действительно близким к родному JS или TS. Надеюсь, это проясняет путаницу. Если у вас есть еще вопросы, просто дайте мне знать 😉

Ух ты! Просто вау! Глупый человек задает глупый вопрос, а умный парень отвечает на трех листах формата А4, полных соответствующей информации и пояснений. 🤯 Ты просто молодец, мужик! Большое спасибо! ❤️ Теперь я понимаю и начну использовать Атрибуты.

По-прежнему рекомендуется как-то называть компоненты (как мы использовали первый параметр React.functionComponent ) или это больше не нужно для атрибутивного подхода?

Теперь я понимаю и вместо этого начну использовать Атрибут.

Потрясающие! Позвольте мне, если вы столкнетесь с какой-либо проблемой 😉 сейчас единственная проблема, о которой нужно знать, - это использование типа записи в качестве входных реквизитов, будет немного проблематично для React-refresh, поэтому вы можете использовать анонимную запись вместо этого или примитивные параметры. Я надеюсь, что проблема скоро будет исправлена, и я смогу задокументировать [<ReactComponent>] без каких-либо оговорок.

По-прежнему рекомендуется как-то называть компоненты (как мы использовали первый параметр React.functionComponent) или это больше не нужно для атрибутивного подхода?

Нет, единственное требование состоит в том, чтобы компоненты были скомпилированы как значения в верхнем регистре, что является одной из вещей, которые [<ReactComponent>] делает с определением функции: smile: вы можете реализовать здесь

@Dzoukr - единственная причина использовать имена для ваших компонентов реакции - это улучшить инструменты отладки.

@Shmew Ага , но в конструкторе ReactComponent нет перегрузки для добавления такого имени, поэтому и спросил.

Итак, продолжая вопросы [<ReactComponent>] vs functionComponent : hooks!

У меня есть компонент, которому нужно инициализировать какое-то состояние. К счастью, у нас есть много хороших крючков! Я пишу это:

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

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

Увы, когда я пытаюсь запустить это, моя консоль печальна и полна ошибок:

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 

Я прошел через шаги отладки реакции выше; ни один из них не кажется правдой. Это должно работать? Это единственное, что есть в Fable 3? (Я все еще использую Fable 2.)

Насколько я понимаю, для работы атрибута reactcomponent требуется fable 3, потому что это плагин компилятора fable 3.

@landy а, это точно

Привет! Да, это меня устранило - я использовал этот PR как ориентир для конверсии.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги