Skip to content

Commit 5d1efd5

Browse files
committed
Added upgrade information
1 parent 0406b7a commit 5d1efd5

1 file changed

Lines changed: 177 additions & 0 deletions

File tree

docs/docs/Upgrade.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
---
2+
title: Upgrade from 2.x to 3.x
3+
displayed_sidebar: docsSidebar
4+
sidebar_position: 999
5+
---
6+
7+
A lot fo F# wrapper magic was removed. React bindings now behave as close as possible to actual React functionality.
8+
9+
## Update Fable Version
10+
11+
Get the latest fable version (currently pre-release).
12+
13+
```bash
14+
# cmd
15+
dotnet tool update fable --prerelease
16+
```
17+
18+
## Update .NET Framework
19+
20+
Recommended is the use of .NET 8.
21+
22+
```bash
23+
# cmd
24+
dotnet --version
25+
```
26+
27+
## React.memo
28+
29+
React.memo is used to meoize the rendering of your components and prevent unnecessary rerenders. The recommended usecase is the attribute [<ReactMemoComponent>] but you can also use [React.memo](https://fable-hub.github.io/Feliz/next/api-docs/react/apis/memo) to define a component for memo. When doing so, the component of React.lazy' must be bind with let and be called with React.lazyRender to render it.
30+
31+
```fsharp
32+
open Feliz
33+
open Browser.Dom
34+
35+
[<ReactComponent>]
36+
let RenderTextWithEffect (text: string) =
37+
React.useEffect (fun () -> console.log("Rerender!", text) )
38+
Html.div [
39+
prop.text text;
40+
prop.testId "memo-attribute"
41+
]
42+
43+
let MemoFunction =
44+
React.memo<{|text: string|}> (fun props ->
45+
RenderTextWithEffect(props.text)
46+
)
47+
48+
[<ReactComponent(true)>]
49+
let Main () =
50+
let isDark, setIsDark = React.useState(false)
51+
let text, setText = React.useState("Hello, world!")
52+
let fgColor = if isDark then color.white else color.black
53+
let bgColor = if isDark then color.black else color.white
54+
Html.div [
55+
prop.style [style.border(1, borderStyle.solid, fgColor); style.padding 20; style.color fgColor; style.backgroundColor bgColor]
56+
prop.children [
57+
Html.h3 "Check the output in the browser console"
58+
Html.button [
59+
prop.text "Toggle Dark Mode"
60+
prop.onClick (fun _ -> setIsDark(not isDark))
61+
]
62+
Html.input [
63+
prop.value text
64+
prop.onChange setText
65+
]
66+
React.memoRender(MemoFunction, {| text = text |})
67+
]
68+
]
69+
```
70+
71+
## React.lazy'
72+
73+
React.lazy' is used to call components dynamically, also only when needed, in order to reduce the required performance. The recommended usecase is the attribute [<ReactLazyComponent>] but you can also define a lazy loaded comonent using [React.lazy'](https://fable-hub.github.io/Feliz/next/api-docs/react/apis/lazy). When doing so, the component of React.lazy' must be bind with let and be called with React.lazyRender to render it.
74+
75+
```fsharp
76+
open Feliz
77+
open Fable.Core
78+
79+
/// Lazy load with delay to simulate large component
80+
///
81+
/// Note: Prefer using `[<ReactLazyComponent>]` instead of this approach!
82+
let LazyHello: LazyComponent<unit> =
83+
React.lazy'(fun () ->
84+
promise {
85+
do! Promise.sleep 2000
86+
return! JsInterop.importDynamic "./Counter"
87+
}
88+
)
89+
90+
[<ReactComponent(true)>]
91+
let SuspenseDemo() =
92+
let load, setLoad = React.useState(false)
93+
Html.div [
94+
Html.h3 [ prop.text "Suspense Example" ]
95+
Html.p "Loading the component will take 2 seconds. Then the component will be cached and future reruns will be instant."
96+
if load then
97+
React.Suspense([
98+
React.lazyRender(LazyHello, ())
99+
],
100+
Html.div [ prop.text "Loading..." ]
101+
)
102+
else
103+
Html.button [
104+
prop.text (if load then "Hide Lazy Component" else "Load Lazy Component")
105+
prop.onClick (fun _ -> setLoad(not load))
106+
]
107+
]
108+
```
109+
110+
## React.context
111+
112+
React.createContext enables the user to create a context for a component in react. That way, values are shared automatically between a component and all its children, without inserting them. In order to use [React.createContext](https://fable-hub.github.io/Feliz/next/api-docs/react/apis/createContext), you must define a reactcontext with a let binding. Then you can call that context in a provider, which inserts the values to be shared in the defined context.Provider and the child components.
113+
114+
```fsharp
115+
open Feliz
116+
open Browser.Dom
117+
118+
open Feliz
119+
120+
// Define a context for shared state
121+
// This can should be placed in a separate file for reuse
122+
let CounterContext = React.createContext(None: (int * (int -> unit)) option)
123+
124+
[<ReactComponent>]
125+
let CounterProvider(children: ReactElement list) =
126+
let count, setCount = React.useState(0)
127+
CounterContext.Provider(Some(count, setCount), children)
128+
129+
[<ReactComponent>]
130+
let CounterDisplay() =
131+
let ctx = React.useContext(CounterContext)
132+
match ctx with
133+
| Some(count, _) -> Html.p [ prop.text $"Current count: {count}" ]
134+
| None -> Html.p [ prop.text "No context available" ]
135+
136+
[<ReactComponent>]
137+
let CounterControls() =
138+
let ctx = React.useContext(CounterContext)
139+
match ctx with
140+
| Some(count, setCount) ->
141+
Html.div [
142+
Html.button [
143+
prop.text "+"
144+
prop.onClick (fun _ -> setCount(count + 1))
145+
]
146+
Html.button [
147+
prop.text "-"
148+
prop.onClick (fun _ -> setCount(count - 1))
149+
]
150+
]
151+
| None -> Html.p [ prop.text "No context available" ]
152+
153+
[<ReactComponent(true)>]
154+
let UseContext() =
155+
CounterProvider [
156+
Html.h3 [ prop.text "Shared Counter" ]
157+
CounterDisplay()
158+
CounterControls()
159+
]
160+
161+
```
162+
163+
## FsReact
164+
165+
All f# functions to help with react interop have been moved to FsReact namespace.
166+
167+
```
168+
FsReact.createDisposable
169+
FsReact.useDisposable
170+
FsReact.useCancellationToken
171+
```
172+
173+
## Components use PascalCase
174+
175+
According to react best practices, components are written in PascalCase instead of camelCase. This has been updated for React.
176+
177+
`React.Fragment, React.KeyedFragment, React.Imported, React.DynamicImported, React.StrictMode, React.Suspense, React.Provider, React.Consumer`

0 commit comments

Comments
 (0)