From 96f090b9912baf2fb195de8a52de06e3832d3b1f Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Fri, 26 Apr 2019 13:12:35 +0300 Subject: [PATCH] Markdown formatting & small fixes --- doc/InteropWithReact.md | 75 +++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/doc/InteropWithReact.md b/doc/InteropWithReact.md index a34b0cb..4739d4e 100644 --- a/doc/InteropWithReact.md +++ b/doc/InteropWithReact.md @@ -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)