Upgrade to v3
A lot fo F# wrapper magic was removed. React bindings now behave as close as possible to actual React functionality.
Update React version
Feliz 3.x requires React 19 or higher. Update your package.json dependencies with
npm i react@19 react-dom@19
Update Fable Version
Get the latest fable version (currently pre-release).
# cmd
dotnet tool update fable --prerelease
Update .NET Framework
Fable 5 is a .NET 10 tool. Check your .NET version with dotnet --version and install a newer version if needed.
If you are using a global.json file to pin your .NET SDK version, make sure to update it.
{
"sdk": {
"version": "10.0.0",
"rollForward": "latestMinor"
}
}
React.memo
React.memo behavior was reworked to improve compatibility with React devtools. It now requires to be called with React.memoRenderer. Check out the docs for more info and alternatives!
let MemoFunction =
React.memo<{|text: string|}> (fun props ->
// some component
)
[<ReactComponent>]
let Main () =
Html.div [
React.memoRender(MemoFunction, {| text = text |})
]
React.lazy'
React.lazy' behavior was reworked. It now requires to be called with React.lazyRenderer. Check out the docs for more info and alternatives!
let LazyHello: LazyComponent<unit> =
React.lazy'(fun () ->
promise {
do! Promise.sleep 2000
return! JsInterop.importDynamic "./Counter"
}
)
[<ReactComponent>]
let SuspenseDemo() =
Html.div [
React.Suspense([
React.lazyRender(LazyHello, ())
],
Html.div [ prop.text "Loading..." ]
)
]
React.context
Using context with React was reworked to more closely align with React functionality. Check out the docs for more info!
// Define a context for shared state
// This can should be placed in a separate file for reuse
let CounterContext = React.createContext(None: (int * (int -> unit)) option)
[<ReactComponent>]
let CounterDisplay() =
let ctx = React.useContext(CounterContext)
match ctx with
| Some(count, _) -> Html.p [ prop.text $"Current count: {count}" ]
| None -> Html.p [ prop.text "No context available" ]
[<ReactComponent(true)>]
let UseContext() =
let count, setCount = React.useState(0)
CounterContext.Provider(
(Some (count, setCount)),
CounterDisplay()
)
FsReact
All F# functions to help with React interop have been moved to FsReact namespace.
FsReact.createDisposableFsReact.useDisposableFsReact.useCancellationToken
Components use PascalCase
According to React best practices, components are written in PascalCase instead of camelCase. This has been updated for React.
React.FragmentReact.KeyedFragmentReact.ImportedReact.DynamicImportedReact.StrictModeReact.SuspenseReact.ProviderReact.Consumer