Skip to content
This repository has been archived by the owner on Nov 13, 2023. It is now read-only.

Commit

Permalink
Add full support for wrapping JS component, and examples.
Browse files Browse the repository at this point in the history
The old way of wrapping components is now deprecated.
  • Loading branch information
cristianoc committed Oct 13, 2018
1 parent 4037e4f commit 50b8e87
Show file tree
Hide file tree
Showing 18 changed files with 443 additions and 164 deletions.
2 changes: 1 addition & 1 deletion examples/reason-react-example/src/interop/MyBanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class App extends React.Component<Props> {
return React.createElement(
"div",
null,
"Here's the message from the owner: " +
"Here's the message from App in JS: " +
(this.props.message != null ? this.props.message : "3")
);
} else {
Expand Down
12 changes: 4 additions & 8 deletions examples/reason-react-example/src/interop/MyBannerRe.bs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 15 additions & 17 deletions examples/reason-react-example/src/interop/MyBannerRe.re
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
/* The @genType annotation is ignored if there's also a .rei file */
[@genType] [@bs.module]
external myBanner: ReasonReact.reactClass = "./MyBanner";
/**
* Wrap component MyBanner to be used from Reason.
*/
[@genType.import "./MyBanner"] /* Module with the JS component to be wrapped. */
[@bs.module "./MyBannerRe.re"] /* This must always be the name of the current module. */
/* The make function will be automatically generated from the types below. */
external make:
(~show: bool, ~message: Js.Nullable.t(string), 'a) =>
ReasonReact.component(
ReasonReact.stateless,
ReasonReact.noRetainedProps,
ReasonReact.actionless,
) =
"";

[@bs.deriving abstract]
type jsProps = {
show: bool,
message: Js.Nullable.t(string),
};

/* The @genType annotation is ignored if there's also a .rei file */
[@genType]
let make = (~show, ~message, children) =>
ReasonReact.wrapJsForReason(
~reactClass=myBanner,
~props=jsProps(~show, ~message),
children,
);
let make = make;
13 changes: 10 additions & 3 deletions examples/reason-react-example/src/interop/MyBannerRe.re.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,15 @@ const React = require('react');
// $FlowExpectedError: Reason checked type sufficiently
const MyBanner = require('./MyBanner');

// $FlowExpectedError: Reason checked type sufficiently
const ReasonReact = require('reason-react/src/ReasonReact.js');

export type Props = {|show: boolean, message: ?string|};

export function checkJsWrapperType(props: Props) {
return <MyBanner {...props}/>;
}
// In case of type error, check the type of 'make' in 'MyBannerRe.re' and the props of './MyBanner'.
export function MyBannerTypeChecked(props: Props) {
return <MyBanner {...props}/>;
}

// Export 'make' early to allow circular import from the '.bs.js' file.
export const make: mixed = function _(show, message, children) { return ReasonReact.wrapJsForReason(MyBanner, {show: show, message: message}, children); };
17 changes: 0 additions & 17 deletions examples/reason-react-example/src/interop/MyBannerRe.rei

This file was deleted.

19 changes: 9 additions & 10 deletions examples/reason-react-example/src/interop/WrapJsValue.re
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* This is the module to import from. */
[@genType.import "./MyMath"]
/* This must always be the name of the current module. */
[@bs.module "./WrapJsValue.re"]
/* This is the name and type of the JS value to bind to. */
/**
* Wrap JS values to be used from Reason
*/
[@genType.import "./MyMath"] /* This is the module to import from. */
[@bs.module "./WrapJsValue.re"] /* This must always be the name of the current module. */
/* Name and type of the JS value to bind to. */
external round: float => float = "";

[@genType]
Expand All @@ -11,11 +12,9 @@ type point = {
y: option(int),
};

/* This is the module to import from. */
[@genType.import "./MyMath"]
/* This must always be the name of the current module. */
[@bs.module "./WrapJsValue.re"]
/* This is the name and type of the JS value to bind to. */
[@genType.import "./MyMath"] /* This is the module to import from. */
[@bs.module "./WrapJsValue.re"] /* This must always be the name of the current module. */
/* Name and type of the JS value to bind to. */
external area: point => int = "";

[@genType]
Expand Down
25 changes: 25 additions & 0 deletions examples/typescript-react-example/src/MyBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as React from "react";
import "./App.css";

// tslint:disable-next-line:interface-name
export interface Props {
show: boolean;
message?: { text: string };
}

class App extends React.PureComponent<Props> {
public render() {
if (this.props.show) {
return (
<div className="App">
{"Here's the message from the owner: " +
(this.props.message === undefined ? "3" : this.props.message.text)}
</div>
);
} else {
return null;
}
}
}

export default App;
13 changes: 5 additions & 8 deletions examples/typescript-react-example/src/MyBannerRe.bs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 16 additions & 19 deletions examples/typescript-react-example/src/MyBannerRe.re
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
/**
* ReactJS used by ReasonReact
* This component wraps a ReactJS one, so that ReasonReact components can consume it
* Typing the myBanner.js component's output as a `reactClass`.
*/
* Wrap component MyBanner to be used from Reason.
*/

[@genType]
[@bs.module]
external myBanner : ReasonReact.reactClass = "./MyBanner";
type message = {text: string};

[@bs.deriving abstract]
type jsProps = {
show: bool,
message: string,
};
[@genType.import "./MyBanner"] /* Module with the JS component to be wrapped. */
[@bs.module "./MyBannerRe"] /* This must always be the name of the current module. */
/* The make function will be automatically generated from the types below. */
external make:
(~show: bool, ~message: option(message)=?, 'a) =>
ReasonReact.component(
ReasonReact.stateless,
ReasonReact.noRetainedProps,
ReasonReact.actionless,
) =
"";

/** This is like declaring a normal ReasonReact component's `make` function, except the body is a the interop hook wrapJsForReason */
[@genType]
let make = (~show, ~message, children) =>
ReasonReact.wrapJsForReason(
~reactClass=myBanner,
~props=jsProps(~show, ~message),
children,
);
let make = make;
19 changes: 14 additions & 5 deletions examples/typescript-react-example/src/MyBannerRe.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
/* Typescript file generated by genType. */

import MyBanner from'./MyBanner';

import * as React from "react";

// tslint:disable-next-line:no-var-requires
const MyBanner = require('./MyBanner');
const ReasonReact = require('reason-react/src/ReasonReact.js');

// tslint:disable-next-line:interface-over-type-literal
export type Props = {show: boolean, message: string};
export type Props = {show: boolean, message?: message};

// In case of type error, check the type of 'make' in 'MyBannerRe.re' and the props of './MyBanner'.
export function MyBannerTypeChecked(props: Props) {
return <MyBanner {...props}/>;
}

export function checkJsWrapperType(props: Props) {
return <MyBanner {...props}/>;
}
// Export 'make' early to allow circular import from the '.bs.js' file.
export const make: unknown = function _(show: any, message: any, children: any) { return ReasonReact.wrapJsForReason(MyBanner, {show: show, message: (message == null ? message : {text:message[0]})}, children); };

// tslint:disable-next-line:interface-over-type-literal
export type message = {text: string};
5 changes: 3 additions & 2 deletions examples/typescript-react-example/src/ReasonComponent.bs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion examples/typescript-react-example/src/ReasonComponent.re
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let component = ReasonReact.statelessComponent("Component");
let component = ReasonReact.statelessComponent("ReasonComponent");

[@genType]
type person('a) = {
Expand Down Expand Up @@ -32,6 +32,7 @@ let make =
)
->ReasonReact.string
}
<MyBannerRe show=true message={Some({text: "this is from ReasonComponent"})} />
</div>,
};

Expand Down
19 changes: 9 additions & 10 deletions examples/typescript-react-example/src/WrapJsValue.re
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* This is the module to import from. */
[@genType.import "./MyMath"]
/* This must always be the name of the current module. */
[@bs.module "./WrapJsValue"]
/* This is the name and type of the JS value to bind to. */
/**
* Wrap JS values to be used from Reason
*/
[@genType.import "./MyMath"] /* This is the module to import from. */
[@bs.module "./WrapJsValue"] /* This must always be the name of the current module. */
/* Name and type of the JS value to bind to. */
external round: float => float = "";

[@genType]
Expand All @@ -11,11 +12,9 @@ type point = {
y: option(int),
};

/* This is the module to import from. */
[@genType.import "./MyMath"]
/* This must always be the name of the current module. */
[@bs.module "./WrapJsValue"]
/* This is the name and type of the JS value to bind to. */
[@genType.import "./MyMath"] /* This is the module to import from. */
[@bs.module "./WrapJsValue"] /* This must always be the name of the current module. */
/* Name and type of the JS value to bind to. */
external area: point => int = "";

[@genType]
Expand Down

0 comments on commit 50b8e87

Please sign in to comment.