Skip to content

Commit c55d0be

Browse files
committed
Split outline into three approaches instead of two, add a TOC to make it easier to understand the structure of the document
1 parent 596fbe8 commit c55d0be

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

docs/using-third-party-react-components.md

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
1-
# Using third party React components
1+
## Using third party React components
22

3-
Using a third party (Javascript) React component is straightforward for most components. There are two ways of declaring a third party React component in F# - either by declaring a Pojo record for the props or by declaring a Discriminated Union where each case has one field.
3+
Using a third party (Javascript) React component is straightforward for most components. There are three ways of declaring a third party React component in F# - either by declaring a Discriminated Union where each case has one field; by declaring a record type for the props with the Pojo attribute; or by using an untyped list of `(string * obj)` tuples. All three ways are described below.
44

55
Some components have a [Typescript](https://www.typescriptlang.org/) definition available, either because the component was authored in Typescript or someone created a type definition for the [Definitely Typed project](https://definitelytyped.org/). If this is the case then you can try the [ts2fable tool](https://github.com/fable-compiler/ts2fable) to convert this React component type definition from Typescript to a Fable type declaration - it might need some tweaking but for components with a big API surface this can be a real time saver.
66

7+
## Table of contents
8+
9+
<!-- TOC -->
10+
11+
- [Using third party React components](#using-third-party-react-components)
12+
- [Table of contents](#table-of-contents)
13+
- [Using a React component by declaring a Discriminated Union props type](#using-a-react-component-by-declaring-a-discriminated-union-props-type)
14+
- [1. Install the react component](#1-install-the-react-component)
15+
- [2. Define the props type](#2-define-the-props-type)
16+
- [3. Define the React component creation function](#3-define-the-react-component-creation-function)
17+
- [4. Use the creation function in your view code](#4-use-the-creation-function-in-your-view-code)
18+
- [Importing using a Pojo (plain old JS object) record](#importing-using-a-pojo-plain-old-js-object-record)
19+
- [Passing in props as tuples (without a type declaration of the props)](#passing-in-props-as-tuples-without-a-type-declaration-of-the-props)
20+
- [Edgecases](#edgecases)
21+
22+
<!-- /TOC -->
23+
724
## Using a React component by declaring a Discriminated Union props type
825

926
The basic steps when working with a Discriminated Union are:
@@ -71,9 +88,11 @@ let view (model : Model) (dispatch : Msg -> unit) =
7188
[ progressLine [ percent model.currentProgress; strokeColor: "red" ] [] ]
7289
```
7390

74-
## Dynamic import using a Pojo
91+
## Importing using a Pojo (plain old JS object) record
92+
93+
The Pojo import is similar to the approach above, but instead of declaring a DU you create a [Pojo record](http://fable.io/docs/interacting.html#plain-old-javascript-objects). Using a record with the Pojo attribute to express the props looks more like idiomatic F# code but it can be unwieldy if you have a lot of optional props. Since this is common with React components, using the DU approach above can often be more convenient.
7594

76-
The dynamic import is similar to the approach above, but instead of declaring a DU you create a Pojo record. This looks more like normal F# code but can be unwieldy if you have a lot of optional props (which is often the case in complex React components)
95+
The Pojo attribute is required on such record types because record definitions without the Pojo attribute get compiled to Javascript classes which cannot be used for props in React; using the Pojo attribute instead instructs the Fable compiler to generate a plain old Js object.
7796

7897
```fsharp
7998
[<Pojo>]
@@ -87,6 +106,17 @@ let inline progressLine (props : ProgressProps) (elems : ReactElement list) : Re
87106
ofImport "Line" "rc-progress" props elems
88107
```
89108

109+
## Passing in props as tuples (without a type declaration of the props)
110+
111+
The third way of using a React component is to not give an F# type to the Props at all and simply pass a list of `(string * obj)` tuples to the `createObj` helper function which turns the list into a Javascript object and passes it as the props of the React component. This of course has the least level of type safety but it can be convenient for prototyping. The `==>` operator is defined in the [Fable.Core.JsInterop](http://fable.io/docs/interacting.html#plain-old-javascript-objects) module to make `(string * obj)` tuple creation easier to read.
112+
113+
```fsharp
114+
open Fable.Core.JsInterop
115+
116+
ofImport "Line" "rc-progress" (createObj ["strokeWidth" ==> 5]) []
117+
```
118+
119+
90120
## Edgecases
91121

92122
This documentation needs to be extended to cover [Higher Order Components](https://reactjs.org/docs/higher-order-components.html) and maybe [Context](https://reactjs.org/docs/context.html), [Fragments](https://reactjs.org/docs/fragments.html) etc. Contributions are welcome!

0 commit comments

Comments
 (0)