Reason
  • Документация
  • Попробовать
  • API
  • Сообщество
  • Блог
  • Languages iconРусский
    • 日本語
    • English
    • Deutsch
    • Español
    • Français
    • 한국어
    • Português (Brasil)
    • Українська
    • 中文
    • 繁體中文
    • Помочь с переводом
  • GitHub

›Advanced Features

Введение

  • Что и зачем

Установка

  • Установка
  • Плагины для редакторов и IDE

Основы языка

  • Обзор
  • Let Bindings
  • Primitives
  • Basic Structures
  • Types
  • Records
  • Variants
  • Options and nullability
  • Functions
  • Recursion
  • Деструктуризация
  • Pattern Matching
  • Mutable Bindings
  • Loops
  • Modules

Advanced Features

  • JSX
  • External
  • Исключения
  • Объекты

JavaScript

  • Взаимодействие с JavaScript
  • Шпаргалка по синтаксису
  • Pipe First
  • Промис
  • Библиотеки
  • Конвертация из JS

Дополнительно

  • Часто задаваемые вопросы (FAQ)
  • Дополнительные инструменты
Translate

JSX

Note: If you are looking for ReasonReact specific JSX infos, please refer to the ReScript JSX docs instead.

Не хотите ли немного HTML синтаксиса в вашем Reason коде? Если нет, то пропустите эту секцию!

Reason поддерживает синтаксис JSX, с некоторыми отличиями от ReactJS. Reason JSX не привязан к ReactJS, он транслируется в обычные вызовы функций:

Заглавный тег

<MyComponent foo={bar} />

becomes

([@JSX] MyComponent.createElement(~foo=bar, ~children=[], ()));

Строчный тег

<div foo={bar}> child1 child2 </div>;

становится

([@JSX] div(~foo=bar, ~children=[child1, child2], ()));

Fragment

<> child1 child2 </>;

становится

([@JSX] [child1, child2]);

Потомок

<MyComponent> foo bar </MyComponent>

This is the syntax for passing a list of two items, foo and bar, to the children position. It desugars to a list containing foo and bar:

([@JSX] MyComponent.createElement(~children=[foo, bar], ()));

So naturally, <MyComponent> foo </MyComponent> desugars to ([@JSX] MyComponent.createElement(~children=[foo], ())). I.e. whatever you do, the arguments passed to the children position will be wrapped in a list. What if you don't want that? What if you want to directly pass foo without an extra wrapping?

Спред дочерних элементов

To solve the above problem, we've introduced

<MyComponent> ...foo </MyComponent>

This passes the value foo without wrapping it in a list. Aka, this desugars to:

([@JSX] MyComponent.createElement(~children=foo, ()));

This is extra useful in the cases where you are handled foo that is already a list of things, and want to forward that without wrapping it an extra time (which would be a type error). It also allows you to pass arbitrary data structures at children position (remember, JSX children is really just a totally normal prop):

<MyComponent> ...((theClassName) => <div className=theClassName />) </MyComponent>;
<MyForm> ...("Hello", "Submit") </MyForm>;

Usage

Here's a JSX tag that shows most of the features.

<MyComponent
  booleanAttribute={true}
  stringAttribute="string"
  intAttribute=1
  forcedOptional=?{Some("hello")}
  onClick={send(handleClick)}>
  <div> {"hello"} </div>
</MyComponent>

Departures From JS JSX

  • Атрибуты и потомки не заключаются в {}, но мы показываем их в любом случае для удобства обучения. Когда вы refmt ваш файл, некоторые из них убираются, а некоторые превращаются в скобки.
  • Отсутствует поддержка спреда свойств как в JSX: <Foo {...bar} />. Хотя есть кое-что похожее, у нас есть спред потомков, описанный выше: <Foo> ...baz </Foo>.
  • Короткие свойства!

Короткое свойство

"Punning" refers to the syntax shorthand for when a label and a value are the same. For example, in JavaScript, instead of doing return {name: name}, you can do return {name}.

Reason JSX supports punning. <input checked /> is just a shorthand for <input checked=checked />. The formatter will help you format to the latter whenever possible. This is convenient in the cases where there are lots of props to pass down:

<MyComponent isLoading text onClick />

Consequently, a Reason JSX component can cram in a few more props before reaching for extra libraries solutions that avoids props passing.

Note that this is a departure from ReactJS JSX, which does not have punning. ReactJS' <input checked /> desugars to <input checked=true />, in order to conform to DOM's idioms and for backward compatibility.

Frameworks using JSX

  • ReveryUI: A ReactJS-like UI framework for building cross-platform GUI applications

Tip & Tricks

For library authors wanting to take advantage of the JSX: the [@JSX] attribute above is a hook for potential ppx macros to spot a function wanting to format as JSX. Once you spot the function, you can turn it into any other expression.

This way, everyone gets to benefit the JSX syntax without needing to opt into a specific library using it.

JSX calls supports the features of labeled functions: optional, explicitly passed optional and optional with default.

Design Decisions

The way we designed this JSX is related to how we'd like to help the language evolve. See the section "What's the point?" in this blog post.

The ability to have macros in the language + the library-agnostic JSX syntax allows every library to potentially have JSX without hassle. This way, we add some visual familiarities to the underlying OCaml language without compromising on its semantics (aka how it executes). One big goal of Reason is to let more folks take advantage of the beautiful language that is OCaml, while discarding the time-consuming debates around syntax and formatting.

← ModulesExternal →
  • Заглавный тег
  • Строчный тег
  • Fragment
    • Потомок
  • Usage
  • Departures From JS JSX
    • Короткое свойство
  • Frameworks using JSX
  • Tip & Tricks
  • Design Decisions