🔥 Suspense/Lazy for ReasonReact.
- Installation
- Support
- Example
- Non-ReasonReact component
- Experimental SuspenseList
- API
- Special thanks to
npm install reason-loadable --save
Then add "reason-loadable" in "bsconfig.json" :
"bs-dependencies": [
"reason-loadable"
]
You can now use "ReLoadable" module.
Note : "ReLoadable" contain type definition, it doesn't add any single bit into your project.
- ReasonReact component (JSX v3). ✔️
- Non-ReasonReact component (third-party React component or your own plain JavaScript React component). ✔️
ReasonReact JSX v2 isn't supported : Please consider migrating to JSX v3 (new ReasonReact hook components).
- Create a ReasonReact hook component (JSX v3).
/* HelloWorld.re */
[@react.component]
let make = (~name) => <h1> (React.string("Hello world " ++ name)) </h1>;
/* Export default is necessary because React lazy function always resolve the default export. */
let default = make;
- Create type-safe lazy component with "ReLoadable.lazy_" and "ReLoadable.import".
/* LazyHelloWorld.re */
module type T = (module type of WithPure);
/*
Needed for BuckleScript to not import the original component :
See https://github.com/BuckleScript/bucklescript/issues/3543
*/
let unsafePlaceholder: module T = [%raw {|{}|}];
module UnsafePlaceholder = (val unsafePlaceholder);
let makeProps = UnsafePlaceholder.makeProps;
let make =
ReLoadable.lazy_(() => ReLoadable.import(UnsafePlaceholder.make, "./HelloWord.bs.js"));
- Render lazy component anywhere in your ReasonReact app with "React.Suspense".
/* App.re */
[@react.component]
let make = () => {
<React.Suspense fallback={<div> (React.string("Loading ...")) </div>}>
<LazyHelloWorld name="Zeus" />
</React.Suspense>;
};
More example are available in repository.
- Create type-safe lazy component with "ReLoadable.lazy_" and "ReLoadable.import".
/* LazyButton.re */
/* You have to type non-ReasonReact component props explicitly. */
module type T = {
[@react.component]
let make: (~text: string) => React.element;
};
/*
Needed for BuckleScript to not import the original component :
See https://github.com/BuckleScript/bucklescript/issues/3543
*/
let unsafePlaceholder: module T = [%raw {|{}|}];
module UnsafePlaceholder = (val unsafePlaceholder);
let makeProps = UnsafePlaceholder.makeProps;
/* "@my-component-lib/button" should have a default export. */
let make =
ReLoadable.lazy_(() => ReLoadable.import(UnsafePlaceholder.make, "@my-component-lib/button"));
- Render lazy component anywhere in your ReasonReact app with "React.Suspense".
/* App.re */
[@react.component]
let make = () => {
<React.Suspense fallback={<div> (React.string("Loading ...")) </div>}>
<LazyButton text="Click !" />
</React.Suspense>;
};
Concurrent mode is only available in the experimental builds of React. To install them, run :
npm install react@experimental react-dom@experimental
There are no semantic versioning guarantees for the experimental builds. APIs may be added, changed, or removed with any @experimental release.
Experimental releases will have frequent breaking changes.
You can try these builds on personal projects or in a branch, but we don’t recommend running them in production.
Sometime, there's breaking change in experimental builds. For example, "createRoot" function has been changed to "unstable_createRoot" recently.
Be prepared to do some research into ReasonReact and React source code if something goes wrong, especially when binding between ReasonReact and React doesn't match due to breaking changes.
Experimental ReasonReact API is available under the "Experimental" module : https://github.com/reasonml/reason-react/blob/master/src/ReactDOMRe.re#L40
Some React experimental builds can break the SuspenseList API.
Here is one experimental build that seem to work well with SuspenseList API : 0.0.0-experimental-aae83a4b9.
npm install react@0.0.0-experimental-aae83a4b9 react-dom@0.0.0-experimental-aae83a4b9
/* App.re */
/* LazyButton and LazyHelloWorld are lazy components (see previous examples). */
[@react.component]
let make = () => {
<React.SuspenseList>
<React.Suspense fallback={<div> (React.string("Loading ...")) </div>}>
<LazyButton text="Click !" />
</React.Suspense>
<React.Suspense fallback={<div> (React.string("Loading ...")) </div>}>
<LazyHelloWorld name="Zeus" />
</React.Suspense>
</React.SuspenseList>;
};
/* index.re */
/* You have to use the experimental createRoot API explicitly. */
let _ =
switch (ReactDOMRe.Experimental.createRootWithId("root")) {
| Ok(root) => ReactDOMRe.Experimental.render(root, <App />)
| Error(err) => Js.log(err)
};
Dynamic import React component.
React.lazy binding.
-
@rickyvetter
-
@bloodyowl
-
@cristianoc
-
@thangngoc89
-
@jchavarri (https://github.com/jchavarri/reason-react-lazy-loading)