mirror of https://github.com/status-im/reagent.git
Markdown formatting & small fixes
This commit is contained in:
parent
901607c45f
commit
96f090b991
|
@ -1,10 +1,13 @@
|
|||
# Interop with React
|
||||
|
||||
A little understanding of what reagent is doing really helps when trying to use React libraries and reagent together.
|
||||
A little understanding of what Reagent is doing really helps when trying to use
|
||||
React libraries and reagent together.
|
||||
|
||||
## Creating React Elements directly
|
||||
|
||||
The `reagent.core/create-element` function simply calls React's `createElement` function (and therefore, it expects either a string representing an HTML element or a React Component).
|
||||
The `reagent.core/create-element` function simply calls React's `createElement`
|
||||
function (and therefore, it expects either a string representing an HTML
|
||||
element or a React Component).
|
||||
|
||||
As an example, here are four ways to create the same element:
|
||||
|
||||
|
@ -28,20 +31,33 @@ As an example, here are four ways to create the same element:
|
|||
[:div.foo "Hello " (r/create-element "strong"
|
||||
#js{}
|
||||
"world")]])
|
||||
|
||||
(defn mount-root []
|
||||
(reagent/render [integration]
|
||||
(.getElementById js/document "app")))
|
||||
```
|
||||
|
||||
This works because `reagent/render` itself expects (1) a React element or (2) a Hiccup form. If passed an element, it just uses it. If passed a Hiccup, it creats a (cached) React component and then creates an element from that component.
|
||||
This works because `reagent/render` itself expects (1) a React element or (2) a
|
||||
Hiccup form. If passed an element, it just uses it. If passed a Hiccup, it
|
||||
creats a (cached) React component and then creates an element from that
|
||||
component.
|
||||
|
||||
## Creating React Elements from Hiccup forms
|
||||
|
||||
The `reagent.core/as-element` function creates a React element from a Hiccup form. In the previous section, we discussed how `reagent/render` expects either (1) a Hiccup form or (2) a React Element. If it encounters a Hiccup form, it calls `as-element` on it. When you have a React component that wraps children, you can pass Hiccup forms to it wrapped in `as-element`.
|
||||
The `reagent.core/as-element` function creates a React element from a Hiccup
|
||||
form. In the previous section, we discussed how `reagent/render` expects either
|
||||
(1) a Hiccup form or (2) a React Element. If it encounters a Hiccup form, it
|
||||
calls `as-element` on it. When you have a React component that wraps children,
|
||||
you can pass Hiccup forms to it wrapped in `as-element`.
|
||||
|
||||
## Creating Reagent "Components" from React Components
|
||||
|
||||
The function `reagent/adapt-react-class` will turn a React Component into something that can be placed into the first position of a Hiccup form, as if it were a Reagent function. Take, for example the react-flip-move library and assume that it has been properly imported as a React Component called `FlipMove`. By wrapping FlipMove with `adapt-react-class`, we can use it in a Hiccup form:
|
||||
The function `reagent/adapt-react-class` will turn a React Component into
|
||||
something that can be placed into the first position of a Hiccup form, as if it
|
||||
were a Reagent function. Take, for example the react-flip-move library and
|
||||
assume that it has been properly imported as a React Component called
|
||||
`FlipMove`. By wrapping FlipMove with `adapt-react-class`, we can use it in a
|
||||
Hiccup form:
|
||||
|
||||
```clojure
|
||||
(defn top-articles [articles]
|
||||
|
@ -51,7 +67,8 @@ The function `reagent/adapt-react-class` will turn a React Component into someth
|
|||
articles]
|
||||
```
|
||||
|
||||
There is also a convenience mechanism `:>` (colon greater-than) that shortens this and avoid some parenthesis:
|
||||
There is also a convenience mechanism `:>` (colon greater-than) that shortens
|
||||
this and avoid some parenthesis:
|
||||
|
||||
```clojure
|
||||
(defn top-articles [articles]
|
||||
|
@ -87,11 +104,16 @@ The `reagent/reactify-component` will take a Form-1, Form-2, or Form-3 reagent "
|
|||
|
||||
Note:
|
||||
|
||||
* `adapt-react-class` and `reactify-component` are not perfectly symmetrical, because `reactify-component` requires that the reagent component accept everything in a single props map, including its children.
|
||||
* `adapt-react-class` and `reactify-component` are not perfectly symmetrical,
|
||||
because `reactify-component` requires that the reagent component accept
|
||||
everything in a single props map, including its children.
|
||||
|
||||
## Example: "Decorator" Higher-Order Components
|
||||
|
||||
Some React libraries use the decorator pattern: a React component which takes a component as an argument and returns a new component as its result. One example is the React DnD library. We will need to use both `adapt-react-class` and `reactify-component` to move back and forth between React and reagent:
|
||||
Some React libraries use the decorator pattern: a React component which takes a
|
||||
component as an argument and returns a new component as its result. One example
|
||||
is the React DnD library. We will need to use both `adapt-react-class` and
|
||||
`reactify-component` to move back and forth between React and reagent:
|
||||
|
||||
```clojure
|
||||
(def react-dnd-component
|
||||
|
@ -100,7 +122,7 @@ Some React libraries use the decorator pattern: a React component which takes a
|
|||
(decorator (reagent/reactify-component top-level-component)))))
|
||||
```
|
||||
|
||||
This is the equivalent javascript:
|
||||
This is the equivalent JavaScript:
|
||||
|
||||
```clojure
|
||||
import HTML5Backend from 'react-dnd-html5-backend';
|
||||
|
@ -115,7 +137,7 @@ export default DragDropContext(HTML5Backend)(TopLevelComponent);
|
|||
|
||||
## Example: Function-as-child Components
|
||||
|
||||
Some React components expect a function as their only child. React autosizer is one such example.
|
||||
Some React components expect a function as their only child. React AutoSizer is one such example.
|
||||
|
||||
```clojure
|
||||
[(reagent/adapt-react-class AutoSizer)
|
||||
|
@ -127,13 +149,23 @@ Some React components expect a function as their only child. React autosizer is
|
|||
|
||||
## Getting props and children of current component
|
||||
|
||||
Because you just pass arguments to reagent functions, you typically don't need to think about "props" and "children" as distinct things. But Reagent does make a distinction and it is helpful to understand this, particularly when interoperating with native elements and React libraries.
|
||||
Because you just pass arguments to reagent functions, you typically don't need
|
||||
to think about "props" and "children" as distinct things. But Reagent does make
|
||||
a distinction and it is helpful to understand this, particularly when
|
||||
interoperating with native elements and React libraries.
|
||||
|
||||
Specifically, if the first argument to your Reagent function is a map, that is assigned to `this.props` of the underlying Reagent component. All other arguments are assigned as children to `this.props.children`.
|
||||
Specifically, if the first argument to your Reagent function is a map, that is
|
||||
assigned to `this.props` of the underlying Reagent component. All other
|
||||
arguments are assigned as children to `this.props.children`.
|
||||
|
||||
When interacting with native React components, it may be helpful to access props and children, which you can do with `reagent.core/current-component`. This function returns an object that allows you retrieve the props and children passed to the current component.
|
||||
When interacting with native React components, it may be helpful to access
|
||||
props and children, which you can do with `reagent.core/current-component`.
|
||||
This function returns an object that allows you retrieve the props and children
|
||||
passed to the current component.
|
||||
|
||||
Beware that `current-component` is only valid in component functions, and must be called outside of e.g event handlers and `for` expressions, so it’s safest to always put the call at the top, as in `my-div` here:
|
||||
Beware that `current-component` is only valid in component functions, and must
|
||||
be called outside of e.g. event handlers and `for` expressions, so it's safest
|
||||
to always put the call at the top, as in `my-div` here:
|
||||
|
||||
```clojure
|
||||
(ns example
|
||||
|
@ -151,21 +183,6 @@ Beware that `current-component` is only valid in component functions, and must b
|
|||
[:p "Some other text in bold."]]])
|
||||
```
|
||||
|
||||
## React Interop Macros
|
||||
|
||||
**Please do not use these macros. They will be removed at some point. Either use extern inference, externs or proper `goog.object/get`.**
|
||||
|
||||
Reagent provides two utility macros `$` and `$!` for getting and setting javascript properties in a way that is safe for advanced compilation.
|
||||
|
||||
`($ o :foo)` is equivalent to `(.-foo o)`
|
||||
`($ o foo arg1 arg2)` is the same as `(.foo o arg1 arg2)`
|
||||
|
||||
Similarly,
|
||||
|
||||
`($! o :foo 1)` is equivalent to `(set! (.-foo o) 1)`
|
||||
|
||||
Note, these are not necessary if your JavaScript library has an externs file or if externs inference is on and working.
|
||||
|
||||
## Examples
|
||||
|
||||
- [Material-UI](../examples/material-ui/src/example/core.cljs)
|
||||
|
|
Loading…
Reference in New Issue