Skip to content

Commit bdf8ec9

Browse files
authored
Revise Upgrade.md for framework and React updates
Updated Upgrade.md to reflect changes in .NET Framework, React.memo, React.lazy, React.context, FsReact namespace, and component naming conventions.
1 parent 5d1efd5 commit bdf8ec9

1 file changed

Lines changed: 32 additions & 97 deletions

File tree

docs/docs/Upgrade.md

Lines changed: 32 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -17,68 +17,34 @@ dotnet tool update fable --prerelease
1717

1818
## Update .NET Framework
1919

20-
Recommended is the use of .NET 8.
20+
Recommended is the use of .NET 8. You can check your local .NET version with `dotnet --version` and update your .fsproj files with
2121

22-
```bash
23-
# cmd
24-
dotnet --version
22+
```xml
23+
<TargetFramework>net8.0</TargetFramework>
2524
```
2625

2726
## React.memo
2827

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.
28+
`React.memo` behavior was reworked to improve compatibility with React devtools. It now **requires** to be called with `React.memoRenderer`. Check out the [docs](./api-docs/react/apis/memo) for more info and alternatives!
3029

3130
```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-
4331
let MemoFunction =
4432
React.memo<{|text: string|}> (fun props ->
45-
RenderTextWithEffect(props.text)
33+
// some component
4634
)
4735
48-
[<ReactComponent(true)>]
36+
[<ReactComponent>]
4937
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
5438
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-
]
39+
React.memoRender(MemoFunction, {| text = text |})
6840
]
6941
```
7042

7143
## React.lazy'
7244

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.
45+
`React.lazy'` behavior was reworked. It now **requires** to be called with `React.lazyRenderer`. Check out the [docs](./api-docs/react/apis/lazy) for more info and alternatives!
7446

7547
```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!
8248
let LazyHello: LazyComponent<unit> =
8349
React.lazy'(fun () ->
8450
promise {
@@ -87,91 +53,60 @@ let LazyHello: LazyComponent<unit> =
8753
}
8854
)
8955
90-
[<ReactComponent(true)>]
56+
[<ReactComponent>]
9157
let SuspenseDemo() =
92-
let load, setLoad = React.useState(false)
9358
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-
]
59+
React.Suspense([
60+
React.lazyRender(LazyHello, ())
61+
],
62+
Html.div [ prop.text "Loading..." ]
63+
)
10764
]
10865
```
10966

11067
## React.context
11168

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.
69+
Using context with React was reworked to more closely align with React functionality.
11370

11471
```fsharp
115-
open Feliz
116-
open Browser.Dom
117-
118-
open Feliz
119-
12072
// Define a context for shared state
12173
// This can should be placed in a separate file for reuse
12274
let CounterContext = React.createContext(None: (int * (int -> unit)) option)
12375
124-
[<ReactComponent>]
125-
let CounterProvider(children: ReactElement list) =
126-
let count, setCount = React.useState(0)
127-
CounterContext.Provider(Some(count, setCount), children)
128-
12976
[<ReactComponent>]
13077
let CounterDisplay() =
13178
let ctx = React.useContext(CounterContext)
13279
match ctx with
13380
| Some(count, _) -> Html.p [ prop.text $"Current count: {count}" ]
13481
| None -> Html.p [ prop.text "No context available" ]
13582
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-
15383
[<ReactComponent(true)>]
15484
let UseContext() =
155-
CounterProvider [
156-
Html.h3 [ prop.text "Shared Counter" ]
85+
let count, setCount = React.useState(0)
86+
CounterContext.Provider(
87+
(Some (count, setCount)),
15788
CounterDisplay()
158-
CounterControls()
159-
]
89+
)
16090
16191
```
16292

16393
## FsReact
16494

165-
All f# functions to help with react interop have been moved to FsReact namespace.
95+
All F# functions to help with React interop have been moved to FsReact namespace.
16696

167-
```
168-
FsReact.createDisposable
169-
FsReact.useDisposable
170-
FsReact.useCancellationToken
171-
```
97+
* `FsReact.createDisposable`
98+
* `FsReact.useDisposable`
99+
* `FsReact.useCancellationToken`
172100

173101
## Components use PascalCase
174102

175-
According to react best practices, components are written in PascalCase instead of camelCase. This has been updated for React.
103+
According to React best practices, components are written in PascalCase instead of camelCase. This has been updated for React.
176104

177-
`React.Fragment, React.KeyedFragment, React.Imported, React.DynamicImported, React.StrictMode, React.Suspense, React.Provider, React.Consumer`
105+
* `React.Fragment`
106+
* `React.KeyedFragment`
107+
* `React.Imported`
108+
* `React.DynamicImported`
109+
* `React.StrictMode`
110+
* `React.Suspense`
111+
* `React.Provider`
112+
* `React.Consumer`

0 commit comments

Comments
 (0)