Skip to main content

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.

warning

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.createDisposable
  • FsReact.useDisposable
  • FsReact.useCancellationToken

Components use PascalCase​

According to React best practices, components are written in PascalCase instead of camelCase. This has been updated for React.

  • React.Fragment
  • React.KeyedFragment
  • React.Imported
  • React.DynamicImported
  • React.StrictMode
  • React.Suspense
  • React.Provider
  • React.Consumer