Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

reason-react

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

reason-react - npm Package Compare versions

Comparing version 0.4.1 to 0.4.2

FUTURE-NATIVE.md

6

bsconfig.json

@@ -9,3 +9,7 @@ /* This is the BuckleScript configuration file. Note that this is a comment;

"refmt": 3,
"bsc-flags": ["-bs-no-version-header"]
"bsc-flags": ["-bs-no-version-header"],
"package-specs": {
"module": "commonjs",
"in-source": true,
}
}

9

docs/clone-element.md
---
title: cloneElement
---
Signature: `let cloneElement: (reactElement, ~props: Js.t({..})=?, 'anyChildrenType) => reactElement`
Same as ReactJS' [cloneElement](https://reactjs.org/docs/react-api.html#cloneelement). However, adding extra props to a ReasonReact component doesn't make sense; you'd use a [**render prop**](https://reactjs.org/docs/render-props.html). Therefore, `ReasonReact.cloneElement` is only used for edge-case interop situations. For example, `data-*` and `aria-*` attributes aren't syntactically valid as a function label. The following doesn't parse:
Same as ReactJS' [cloneElement](https://reactjs.org/docs/react-api.html#cloneelement). However, adding extra props to a ReasonReact component doesn't make sense; you'd use a [**render prop**](https://reactjs.org/docs/render-props.html). Therefore, `ReasonReact.cloneElement` is only used for edge-case interop situations. For example, `data-*` attributes aren't syntactically valid as a function label. The following doesn't parse:
```reason
<div data-payload=1 aria-label="click me" className="foo" />
<div data-payload=1 className="foo" />
```

@@ -18,3 +19,3 @@

<div className="foo" />,
~props={"data-payload": 1, "aria-label": "click me"},
~props={"data-payload": 1},
[||]

@@ -24,3 +25,3 @@ );

This will assign the extra `data-payload` and `aria-label` props (**both untyped**, be careful!) onto the `div`, through a clever, syntactically valid use of Reason's JS object sugar for [BuckleScript objects](https://bucklescript.github.io/docs/en/object.html#object-as-record).
This will assign the extra `data-payload` props (**untyped**, be careful!) onto the `div`, through a clever, syntactically valid use of Reason's JS object sugar for [BuckleScript objects](https://bucklescript.github.io/docs/en/object.html#object-as-record).

@@ -27,0 +28,0 @@ For non-DOM components, you need to use valid prop names.

@@ -28,3 +28,2 @@ ---

Some(Js.Global.setInterval(() => self.send(Tick), 1000));
ReasonReact.NoUpdate;
},

@@ -31,0 +30,0 @@ willUnmount: self => {

@@ -50,23 +50,49 @@ ---

### ReasonReact using ReactJS
### Usage
A ReasonReact component **is not** a ReactJS component. We provide hooks to communicate between the two.
Whether you're using an existing ReactJS component or providing a ReasonReact component for consumption on the JS side, you need to establish the type of the JS props you'd convert from/to, by using [BuckleScript's `bs.deriving abstract`](https://bucklescript.github.io/docs/en/object.html):
```reason
[@bs.deriving abstract]
type jsProps = {
/* some example fields */
className: string,
/* `type` is reserved in Reason. use `type_` and make it still compile to the
JS key `type` */
[@bs.as "type"] type_: string,
value: Js.nullable(int),
};
```
This will generate the getters and the JS object creation function (of the same name, `jsProps`) you'll need.
#### ReasonReact using ReactJS
Easy! Since other Reason components only need you to expose a `make` function, fake one up:
```reason
[@bs.module] external myJSReactClass : ReasonReact.reactClass = "./myJSReactClass";
[@bs.module] external myJSReactClass: ReasonReact.reactClass = "./myJSReactClass";
let make = (~name: string, ~age: option(int)=?, children) =>
let make = (~className, ~type_, ~value=?, children) =>
ReasonReact.wrapJsForReason(
~reactClass=myJSReactClass,
~props={"name": name, "age": Js.Nullable.fromOption(age)},
children
~props=jsProps(
~className,
~type_,
~value=Js.Nullable.fromOption(value),
),
children,
);
```
`ReasonReact.wrapJsForReason` is the helper we expose for this purpose. It takes in the `reactClass` you want to wrap, the `props` js object (of type `Js.t {. foo: bar}`) you'd pass to it (with values converted from Reason data structures to JS), and the mandatory children you'd forward to the JS side.
`ReasonReact.wrapJsForReason` is the helper we expose for this purpose. It takes in:
- The `reactClass` you want to wrap
- The `props` js object you'd create through the generated `jsProps` function from the `jsProps` type you've declared above (with values **properly converted** from Reason data structures to JS)
- The mandatory children you'd forward to the JS side.
`props` is mandatory. If you don't have any to pass, pass `~props=Js.Obj.empty()` instead.
**We recommend** to type the `make` parameters, since they're passed to `props` into the JS side, which is untyped.
**Note**: if your app successfully compiles, and you see the error "element type is invalid..." in your console, you might be hitting [this mistake](element-type-is-invalid.md).

@@ -82,11 +108,25 @@

[@bs.deriving abstract]
type jsProps = {
name: string,
age: Js.nullable(int),
};
let jsComponent =
ReasonReact.wrapReasonForJs(
~component,
(jsProps) => make(~name=jsProps##name, ~age=?Js.Nullable.to_opt(jsProps##age), [||])
ReasonReact.wrapReasonForJs(~component, jsProps =>
make(
~name=jsProps |. name,
~age=?Js.Nullable.toOption(jsProps |. age),
[||],
)
);
```
The function takes in the labeled reason `component` you've created, and a function that, given the JS props, asks you to call `make` while passing in the correctly converted parameters. You'd assign the whole thing to the name `jsComponent`. The JS side can then import it:
The function takes in:
- The labeled reason `component` you've created
- A function that, given the JS props, asks you to call `make` while passing in the correctly converted parameters (`bs.deriving abstract` above generates a field accessor for every record field you've declared).
You'd assign the whole thing to the name `jsComponent`. The JS side can then import it:
```

@@ -93,0 +133,0 @@ var MyReasonComponent = require('./myReasonComponent.bs').jsComponent;

@@ -7,3 +7,7 @@ ---

### The component "Greeting"
```reason
/* file: Greeting.re */
let component = ReasonReact.statelessComponent("Greeting");

@@ -14,4 +18,14 @@

...component,
render: (_self) => <button> {ReasonReact.string("Hello!")} </button>
render: (_self) => <button> {ReasonReact.string("Hello " ++ name ++ "!")} </button>
};
```
### An usage of the component
(assuming there's a `div` on the page with id `greeting`)
```reason
/* file: Index.re */
ReactDOMRe.renderToElementWithId(<Greeting name="John" />, "greeting");
```

@@ -5,6 +5,8 @@ ---

Prop names like `type` (as in `<input type="text" />`) aren't syntactically valid; `type` is a reserved keyword in Reason/OCaml. Use `<input _type="text" />` instead. This follows BuckleScript's [name mangling rules](https://bucklescript.github.io/docs/en/object.html#invalid-field-names).
Prop names like `type` (as in `<input type="text" />`) aren't syntactically valid; `type` is a reserved keyword in Reason/OCaml. Use `<input type_="text" />` instead. This follows BuckleScript's [name mangling rules](https://bucklescript.github.io/docs/en/object.html#invalid-field-names).
For `data-*` and `aria-*`, this is a bit trickier; words with `-` in them aren't valid in Reason/OCaml. When you do want to write them, e.g. `<div aria-label="click me" />`, use [`cloneElement`](clone-element.md) as a workaround.
For `aria-*`: use the camelCased `ariaFoo`. E.g. `ariaLabel`. For DOM components, we'll translate it to `aria-label` under the hood.
For `data-*`, this is a bit trickier; words with `-` in them aren't valid in Reason/OCaml. When you do want to write them, e.g. `<div data-name="click me" />`, use [`cloneElement`](clone-element.md) as a workaround.
For non-DOM components, you need to pick valid prop names.

@@ -8,2 +8,5 @@ ---

```reason
/* ReasonReact used by ReactJS */
/* This is just a normal stateless component. The only change you need to turn
it into a ReactJS-compatible component is the wrapReasonForJs call below */
let component = ReasonReact.statelessComponent("PageReason");

@@ -13,3 +16,3 @@

...component,
render: (_self) => {
render: _self => {
let greeting =

@@ -20,15 +23,24 @@ switch (extraGreeting) {

};
<div> <MyBannerRe show=true message={message ++ " " ++ greeting} /> </div>
}
<div> <MyBannerRe show=true message={message ++ " " ++ greeting} /> </div>;
},
};
/* The following exposes a `jsComponent` that the ReactJS side can use as
require('greetingRe.js').jsComponent */
[@bs.deriving abstract]
type jsProps = {
message: string,
extraGreeting: Js.nullable(string),
};
/* if **you know what you're doing** and have
the correct babel/webpack setup, you can also do `let default = ...` and use it
on the JS side as a default export. */
let jsComponent =
ReasonReact.wrapReasonForJs(
~component,
(jsProps) =>
make(
~message=jsProps##message,
~extraGreeting=?Js.Nullable.to_opt(jsProps##extraGreeting),
[||]
)
ReasonReact.wrapReasonForJs(~component, jsProps =>
make(
~message=jsProps |. message,
~extraGreeting=?Js.Nullable.toOption(jsProps |. extraGreeting),
[||],
)
);

@@ -35,0 +47,0 @@ ```

@@ -16,4 +16,4 @@ ---

let setSectionRef = (theRef, {ReasonReact.state}) => {
state.mySectionRef := Js.Nullable.to_opt(theRef);
/* wondering about Js.Nullable.to_opt? See the note below */
state.mySectionRef := Js.Nullable.toOption(theRef);
/* wondering about Js.Nullable.toOption? See the note below */
};

@@ -31,3 +31,3 @@

Attaching to a React DOM element looks the same: `state.mySectionRef = {myDivRef: Js.Nullable.to_opt(theRef)}`.
Attaching to a React DOM element looks the same: `state.mySectionRef = {myDivRef: Js.Nullable.toOption(theRef)}`.

@@ -34,0 +34,0 @@ **Note** how [ReactJS refs can be null](https://github.com/facebook/react/issues/9328#issuecomment-298438237). Which is why `theRef` and `myDivRef` are converted from a [JS nullable](https://bucklescript.github.io/docs/en/null-undefined-option.html) to an OCaml `option` (Some/None). When you use the ref, you'll be forced to handle the null case through a `switch`, which prevents subtle errors!

@@ -28,15 +28,20 @@ ---

```reason
/* Typing the MyBanner.js component's output as a `reactClass`. */
/* Note that this file's JS output is located at reason-react-example/lib/js/src/interop/MyBannerRe.js; we're specifying the relative path to MyBanner.js in the string below */
[@bs.module] external myBanner : ReasonReact.reactClass = "../../../../src/interop/MyBanner";
/* 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`. */
[@bs.module] external myBanner : ReasonReact.reactClass = "./MyBanner";
[@bs.deriving abstract]
type jsProps = {
show: bool,
message: string,
};
/* This is like declaring a normal ReasonReact component's `make` function, except the body is a the interop hook wrapJsForReason */
let make = (~show, ~message, children) =>
ReasonReact.wrapJsForReason(
~reactClass=myBanner,
~props={
"show": show
"message": message /* OCaml string maps to JS string, no conversion needed here */
},
children
~props=jsProps(~show, ~message),
children,
);
```

@@ -0,1 +1,8 @@

# 0.4.2
**This release requires `bs-platform 3.1.4`**.
- DOM components now support `aria-*` attributes without needing hacks: `<div ariaLabel="foo" />`. The camelCase `ariaStuff` will compile to `aria-stuff`.
- For DOM props, instead of `_open`, `_type`, `_begin`, `_end`, `_in`, `_to`, use the new trailing underscore version for consistency: `open_`, `type_`, etc. The former leading underscore versions are now **deprecated**.
# 0.4.1

@@ -2,0 +9,0 @@

{
"name": "reason-react",
"version": "0.4.1",
"version": "0.4.2",
"description": "React bindings for Reason",

@@ -25,3 +25,3 @@ "main": "index.js",

"devDependencies": {
"bs-platform": "^3.0.0"
"bs-platform": "^3.1.4"
},

@@ -28,0 +28,0 @@ "dependencies": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc