|
1 | | -To use a third-party React library in a SAFE application, you need to write an F# wrapper around it. There are two ways for doing this - using [Fable.React](https://www.nuget.org/packages/Fable.React/) or using [Feliz](https://zaid-ajaj.github.io/Feliz/). |
| 1 | +To use a third-party React library in a SAFE application, you need to write an F# wrapper around it. There are two ways for doing this - using [Feliz](https://zaid-ajaj.github.io/Feliz/) or using [Fable.React](https://www.nuget.org/packages/Fable.React/). |
2 | 2 | ## Prerequisites |
3 | 3 |
|
4 | 4 | This recipe uses the [react-d3-speedometer NPM package](https://www.npmjs.com/package/react-d3-speedometer) for demonstration purposes. [Add it to your Client](../package-management/add-npm-package-to-client.md) before continuing. |
5 | 5 |
|
6 | | -## Fable.React - Setup |
7 | | - |
8 | | -#### 1. Create a new file |
9 | | - |
10 | | -Create an empty file named `ReactSpeedometer.fs` in the Client project above `Index.fs` and insert the following statements at the beginning of the file. |
11 | | - |
12 | | -```fsharp |
13 | | -module ReactSpeedometer |
14 | | -
|
15 | | -open Fable.Core |
16 | | -open Fable.Core.JsInterop |
17 | | -open Fable.React |
18 | | -``` |
19 | | - |
20 | | -#### 2. Define the Props |
21 | | -Prop represents the props of the React component. In this recipe, we're using [the props listed here](https://www.npmjs.com/package/react-d3-speedometer) for `react-d3-speedometer`. We model them in Fable.React using a discriminated union. |
22 | | - |
23 | | -```fsharp |
24 | | -type Prop = |
25 | | - | Value of int |
26 | | - | MinValue of int |
27 | | - | MaxValue of int |
28 | | - | StartColor of string |
29 | | -``` |
30 | | - |
31 | | -> One difference to note is that we use **P**ascalCase rather than **c**amelCase. |
32 | | -> |
33 | | -> Note that we can model any props here, both simple values and "event handler"-style ones. |
34 | | -
|
35 | | -#### 3. Write the Component |
36 | | -Add the following function to the file. Note that the last argument passed into the `ofImport` function is a list of `ReactElements` to be used as children of the react component. In this case, we are passing an empty list since the component doesn't have children. |
37 | | - |
38 | | -```fsharp |
39 | | -let reactSpeedometer (props : Prop list) : ReactElement = |
40 | | - let propsObject = keyValueList CaseRules.LowerFirst props // converts Props to JS object |
41 | | - ofImport "default" "react-d3-speedometer" propsObject [] // import the default function/object from react-d3-speedometer |
42 | | -``` |
43 | | - |
44 | | -#### 4. Use the Component |
45 | | -With all these in place, you can use the React element in your client like so: |
46 | | - |
47 | | -```fsharp |
48 | | -open ReactSpeedometer |
49 | | -
|
50 | | -reactSpeedometer [ |
51 | | - Prop.Value 10 // Since Value is already decalred in HTMLAttr you can use Prop.Value to tell the F# compiler its of type Prop and not HTMLAttr |
52 | | - MaxValue 100 |
53 | | - MinValue 0 |
54 | | - StartColor "red" |
55 | | - ] |
56 | | -``` |
57 | | - |
58 | 6 | ## Feliz - Setup |
59 | 7 |
|
60 | 8 | If you don't already have [Feliz](https://www.nuget.org/packages/Feliz/) installed, [add it to your client](../ui/add-feliz.md). |
@@ -108,5 +56,54 @@ That's the bare minimum needed to get going! |
108 | 56 | Once your component is working you may want to extract out the logic so that it can be used in multiple pages of your app. |
109 | 57 | For a full detailed tutorial head over to [this blog post](https://www.compositional-it.com/news-blog/f-wrappers-for-react-components/)! |
110 | 58 |
|
| 59 | +## Fable.React - Setup |
| 60 | + |
| 61 | +#### 1. Create a new file |
| 62 | + |
| 63 | +Create an empty file named `ReactSpeedometer.fs` in the Client project above `Index.fs` and insert the following statements at the beginning of the file. |
| 64 | + |
| 65 | +```fsharp |
| 66 | +module ReactSpeedometer |
| 67 | +
|
| 68 | +open Fable.Core |
| 69 | +open Fable.Core.JsInterop |
| 70 | +open Fable.React |
| 71 | +``` |
| 72 | + |
| 73 | +#### 2. Define the Props |
| 74 | +Prop represents the props of the React component. In this recipe, we're using [the props listed here](https://www.npmjs.com/package/react-d3-speedometer) for `react-d3-speedometer`. We model them in Fable.React using a discriminated union. |
| 75 | + |
| 76 | +```fsharp |
| 77 | +type Prop = |
| 78 | + | Value of int |
| 79 | + | MinValue of int |
| 80 | + | MaxValue of int |
| 81 | + | StartColor of string |
| 82 | +``` |
| 83 | + |
| 84 | +> One difference to note is that we use **P**ascalCase rather than **c**amelCase. |
| 85 | +> |
| 86 | +> Note that we can model any props here, both simple values and "event handler"-style ones. |
111 | 87 |
|
| 88 | +#### 3. Write the Component |
| 89 | +Add the following function to the file. Note that the last argument passed into the `ofImport` function is a list of `ReactElements` to be used as children of the react component. In this case, we are passing an empty list since the component doesn't have children. |
| 90 | + |
| 91 | +```fsharp |
| 92 | +let reactSpeedometer (props : Prop list) : ReactElement = |
| 93 | + let propsObject = keyValueList CaseRules.LowerFirst props // converts Props to JS object |
| 94 | + ofImport "default" "react-d3-speedometer" propsObject [] // import the default function/object from react-d3-speedometer |
| 95 | +``` |
112 | 96 |
|
| 97 | +#### 4. Use the Component |
| 98 | +With all these in place, you can use the React element in your client like so: |
| 99 | + |
| 100 | +```fsharp |
| 101 | +open ReactSpeedometer |
| 102 | +
|
| 103 | +reactSpeedometer [ |
| 104 | + Prop.Value 10 // Since Value is already decalred in HTMLAttr you can use Prop.Value to tell the F# compiler its of type Prop and not HTMLAttr |
| 105 | + MaxValue 100 |
| 106 | + MinValue 0 |
| 107 | + StartColor "red" |
| 108 | + ] |
| 109 | +``` |
0 commit comments