reason-react
Advanced tools
Comparing version 0.7.0-alpha.0 to 0.7.0
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
This section describes how ReactJS' `<div onClick={this.handleClick} />` pattern translates into ReasonReact. | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
ReasonReact children are like ReactJS children, except we provide more bells and whistles that leverages the language itself. | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
Signature: `let cloneElement: (reactElement, ~props: Js.t({..})=?, 'anyChildrenType) => reactElement` | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
_The documentation assumes relative familiarity with ReactJS._ | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
A common pattern in ReactJS is to attach extra variables onto a component's spec: | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
## Project Setup | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
In addition to the [primary JSX transform](jsx.md), you can also use JSX to call older Record components. To do so you can add a `[@bs.config {jsx: 2}];` configuration attribute at the top of a file. Within that file all JSX tags will desugar to the form described here. | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
ReasonReact supports the familiar ReactJS lifecycle events. | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
_Not to be confused with Reason `ref`, the language feature that enables mutation_. | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
`render` needs to return a `ReasonReact.reactElement`: `<div />`, `<MyComponent />`, etc. Render takes the argument `self`: | ||
@@ -7,0 +11,0 @@ |
@@ -11,9 +11,10 @@ --- | ||
[Here's the documented public interface](https://github.com/reasonml/reason-react/blob/9e9e40ea4c7e8d55e56cba47a4d0188c26d0791e/src/ReasonReact.rei#L248-L276), repeated here: | ||
[Here's the documented public interface](https://github.com/reasonml/reason-react/blob/master/src/ReasonReactRouter.rei), repeated here: | ||
- `ReasonReact.Router.push(string)`: takes a new path and update the URL. | ||
- `ReasonReact.Router.replace(string)`: like `push`, but replaces the current URL. | ||
- `ReasonReact.Router.watchUrl(f)`: start watching for URL changes. Returns a subscription token. Upon url change, calls the callback and passes it the `ReasonReact.Router.url` record. | ||
- `ReasonReact.Router.unwatchUrl(watcherID)`: stop watching for url changes. | ||
- `ReasonReact.Router.dangerouslyGetInitialUrl()`: get `url` record outside of `watchUrl`. Described later. | ||
- `ReasonReactRouter.push(string)`: takes a new path and update the URL. | ||
- `ReasonReactRouter.replace(string)`: like `push`, but replaces the current URL. | ||
- `ReasonReactRouter.watchUrl(f)`: start watching for URL changes. Returns a subscription token. Upon url change, calls the callback and passes it the `ReasonReactRouter.url` record. | ||
- `ReasonReactRouter.unwatchUrl(watcherID)`: stop watching for url changes. | ||
- `ReasonReactRouter.dangerouslyGetInitialUrl()`: get `url` record outside of `watchUrl`. Described later. | ||
- `ReasonReactRouter.useUrl(~serverUrl)`: get access to the current url as a hook in your React component. No need to setup `watch`, `unwatch`, and `dangerouslyGetInitialUrl` yourself. | ||
@@ -48,18 +49,14 @@ ## Match a Route | ||
```reason | ||
let watcherID = ReasonReact.Router.watchUrl(url => { | ||
switch (url.path) { | ||
| ["book", id, "edit"] => handleBookEdit(id) | ||
| ["book", id] => getBook(id) | ||
| ["book", id, _] => noSuchBookOperation() | ||
| [] => showMainPage() | ||
| ["shop"] | ["shop", "index"] => showShoppingPage() | ||
| ["shop", ...rest] => | ||
/* e.g. "shop/cart/10", but let "cart/10" be handled by another function */ | ||
nestedMatch(rest) | ||
| _ => showNotFoundPage() | ||
} | ||
}); | ||
/* some time later */ | ||
ReasonReact.Router.unwatchUrl(watcherID); | ||
let url = ReasonReactRouter.useUrl(); | ||
switch (url.path) { | ||
| ["book", id, "edit"] => handleBookEdit(id) | ||
| ["book", id] => getBook(id) | ||
| ["book", id, _] => noSuchBookOperation() | ||
| [] => showMainPage() | ||
| ["shop"] | ["shop", "index"] => showShoppingPage() | ||
| ["shop", ...rest] => | ||
/* e.g. "shop/cart/10", but let "cart/10" be handled by another function */ | ||
nestedMatch(rest) | ||
| _ => showNotFoundPage() | ||
}; | ||
``` | ||
@@ -71,49 +68,29 @@ | ||
Notice that this is just normal [pattern matching](https://reasonml.github.io/docs/en/pattern-matching.html). You can combine it with other features, such as tuple + ReasonReact features like [subscriptions](subscriptions-helper.md) and reducer: | ||
Notice that this is just normal [pattern matching](https://reasonml.github.io/docs/en/pattern-matching.html): | ||
```reason | ||
let component = ReasonReact.reducerComponent("TodoApp"); | ||
[@react.component] | ||
let make = () => { | ||
let url = ReasonReactRouter.useUrl(); | ||
let make = _children => { | ||
...component, | ||
reducer: (action, state) => | ||
switch (action) { | ||
/* router actions */ | ||
| ShowAll => ReasonReact.Update({...state, nowShowing: AllTodos}) | ||
| ShowActive => /* ... */ | ||
/* todo actions */ | ||
| ChangeTodo(text) => /* ... */ | ||
}, | ||
didMount: self => { | ||
let watcherID = ReasonReact.Router.watchUrl(url => { | ||
switch (url.hash, MyAppStatus.isUserLoggedIn) { | ||
| ("active", _) => self.send(ShowActive) | ||
| ("completed", _) => self.send(ShowCompleted) | ||
| ("shared", true) => self.send(ShowShared) | ||
| ("shared", false) when isSpecialUser => /* handle this state please */ | ||
| ("shared", false) => /* handle this state please */ | ||
| _ => self.send(ShowAll) | ||
} | ||
}); | ||
self.onUnmount(() => ReasonReact.Router.unwatchUrl(watcherID)); | ||
}, | ||
render: ... | ||
let nowShowing = | ||
switch (url.hash, MyAppStatus.isUserLoggedIn) { | ||
| ("active", _) => Active | ||
| ("completed", _) => Completed | ||
| ("shared", true) => Shared | ||
| ("shared", false) when isSpecialUser => /* handle this state please */ | ||
| ("shared", false) => /* handle this state please */ | ||
| _ => All | ||
}; | ||
/* ... */ | ||
} | ||
``` | ||
## Directly Get a Route | ||
In one specific occasion, you might want to take hold of a `url` record _outside_ of `watchUrl`. For example, if you've put `watchUrl` inside a component's `didMount` so that a URL change triggers a component state change, you might also want the initial state to be dictated by the URL. | ||
In other words, you'd like to read from the `url` record once at the beginning of your app logic. We expose `dangerouslyGetInitialUrl()` for this purpose. | ||
**Note**: the reason why we label it as "dangerous" is to remind you **not** to read this `url` in any arbitrary component's e.g. `render`, since that information might be out of date if said component doesn't also contain a `watchUrl` subscription that re-renders the component when the URL changes. Aka, please only use `dangerouslyGetInitialUrl` alongside `watchUrl`. | ||
## Push a New Route | ||
From anywhere in your app, just call e.g. `ReasonReact.Router.push("/books/10/edit#validated")`. This will trigger a URL change (without a page refresh) and `watchUrl`'s callback will be called again. | ||
From anywhere in your app, just call e.g. `ReasonReactRouter.push("/books/10/edit#validated")`. This will trigger a URL change (without a page refresh) and components with `useUrl`s will be re-rendered. | ||
We might provide better facilities for typed routing + payload carrying in the future! | ||
**Note**: because of browser limitations, changing the URL through JavaScript (aka `pushState`) **cannot** be detected. The solution is to change the URL then fire a `"popState"` event. This is what `Router.push` does, and what the event `watchUrl` listens to. So if, for whatever reason (e.g. incremental migration), you want to update the URL outside of `Router.push`, just do `window.dispatchEvent(new Event('popState'))`. | ||
**Note**: because of browser limitations, changing the URL through JavaScript (aka `pushState`) **cannot** be detected. The solution is to change the URL then fire a `"popState"` event. This is what `Router.push` does, and what the event `useUrl` listens to. So if, for whatever reason (e.g. incremental migration), you want to update the URL outside of `Router.push`, just do `window.dispatchEvent(new Event('popState'))`. | ||
@@ -120,0 +97,0 @@ ## Design Decisions |
@@ -5,2 +5,6 @@ --- | ||
<aside class="warning"> | ||
The Record API is in feature-freeze. For the newest features and better support going forward, please consider migrating to the new <a href="https://reasonml.github.io/docs/en/components">function componenents</a>. | ||
</aside> | ||
Finally, we're getting onto stateful components! | ||
@@ -7,0 +11,0 @@ |
@@ -5,2 +5,3 @@ 'use strict'; | ||
var React = require("react"); | ||
var Caml_obj = require("bs-platform/lib/js/caml_obj.js"); | ||
@@ -158,3 +159,3 @@ function safeMakeEvent(eventName) { | ||
var newUrl = url(/* () */0); | ||
if (newUrl !== url$1) { | ||
if (Caml_obj.caml_notequal(newUrl, url$1)) { | ||
Curry._1(setUrl, (function (param) { | ||
@@ -161,0 +162,0 @@ return newUrl; |
{ | ||
"name": "reason-react", | ||
"version": "0.7.0-alpha.0", | ||
"version": "0.7.0", | ||
"description": "React bindings for Reason", | ||
@@ -25,3 +25,3 @@ "main": "lib/js/src/ReasonReact.js", | ||
"devDependencies": { | ||
"bs-platform": "^4.0.6" | ||
"bs-platform": "^5.0.1" | ||
}, | ||
@@ -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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
5232278
3247
49