Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into create-root-option
Browse files Browse the repository at this point in the history
  • Loading branch information
bloodyowl committed May 7, 2020
2 parents 67a2e13 + b8c28f4 commit f2ee693
Show file tree
Hide file tree
Showing 24 changed files with 306 additions and 1,677 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ finalOutput/*.js
.merlin
.install
/lib/bs/
/lib/js/
/lib/ocaml/
*.log
.bsb.lock
/src/*.js
_esy
_build
*.install
*.bs.js

# Editor
/.idea/
2 changes: 1 addition & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Thanks to all of our contributors for making this happen!

### Breaking Changes:

* `bs-platform` has a minimum version of 7.0.1 (^7.0.1) [@imbsky in #503](https://github.com/reasonml/reason-react/pull/503)
* `bs-platform` has a minimum version of 7.1.1 (^7.1.1) [@imbsky in #503](https://github.com/reasonml/reason-react/pull/503)
* Adds `onInvalid` prop [@bsansouci in #364](https://github.com/reasonml/reason-react/pull/364)
* Adds `React.float` and `React.int` [@utkarshkukreti in #420](https://github.com/reasonml/reason-react/pull/420)
* Fix `crossOrigin` case and type [@schmavery in #469](https://github.com/reasonml/reason-react/pull/469)
Expand Down
84 changes: 71 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,106 @@
# [ReasonReact](https://reasonml.github.io/reason-react/)
# [ReasonReact](https://reasonml.github.io/reason-react/) - ReasonML / BuckleScript bindings for React.js

[![Chat](https://img.shields.io/discord/235176658175262720.svg?logo=discord&colorb=blue)](https://discord.gg/reasonml)
[![npm version](https://badge.fury.io/js/reason-react.svg)](https://www.npmjs.com/package/reason-react)
![npm](https://img.shields.io/npm/dt/reason-react)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
![contributors](https://img.shields.io/github/contributors/reasonml/reason-react)
[![discord](https://img.shields.io/discord/235176658175262720.svg?logo=discord&colorb=blue)](https://discord.gg/reasonml)
[![twitter](https://img.shields.io/twitter/follow/reasonml?style=social)](https://twitter.com/reasonml)

ReasonReact is a safer, simpler way to build React components. You get a great type system with an even better developer experience. Why choose ReasonReact? Read more [here](https://reasonml.github.io/reason-react/docs/en/what-and-why)

ReasonReact is just React.js under the hood. This makes it super easy to integrate with your current Next.js, Create React App, JavaScript, Flowtype or TypeScript project. Learn more about getting started [here](https://reasonml.github.io/reason-react/docs/en/installation#adding-reason-to-an-existing-reactjs-project-create-react-app-nextjs-etc)

> Watch Ricky Vetter's Reason Conf talk, ["Why React is Just Better in Reason"](https://www.youtube.com/watch?v=i9Kr9wuz24g) to learn more about how Facebook & Messenger are using ReasonReact
> Watch Jordan Walke's Reason Conf talk, ["React to the Future"](https://www.youtube.com/watch?v=5fG_lyNuEAw) to learn more about the future of ReasonML and React
## Example

```reason
/* Greeting.re */
[@react.component]
let make = (~name) => <h1> {React.string("Hello " ++ name)} </h1>
```

in another file:
See all of our examples [here](https://reasonml.github.io/reason-react/docs/en/simple). For a full application, check out [reason-react-hacker-news](https://github.com/reasonml-community/reason-react-hacker-news).

```reason
ReactDOMRe.renderToElementWithId(<Greeting name="Taylor" />, "root");
```
## Getting Started

For a more in-depth example, see: https://github.com/reasonml-community/reason-react-hacker-news
[BuckleScript](http://bucklescript.github.io/) is how your ReasonML code gets compiled to Javascript. Every project that uses BuckleScript will have a `bsconfig.json` file (the same way you'd have tsconfig.json in a Typescript project) with project specific settings.

## Quick start

[BuckleScript](http://bucklescript.github.io/) compiles ReasonML code to JavaScript. You can get it with:
You can install BuckleScript globally or keep it project specific by adding it as a `devDependency`:

```sh
yarn global add bs-platform

# or npm
npm install --global bs-platform
```

If you install BuckleScript globally, you can quickly generate a ReasonReact project template (similar to `create-react-app`):

```sh
bsb -init my-react-app -theme react-hooks
cd my-react-app && npm install && npm start

# in another tab
npm run server
```

If you're interested in adding ReasonReact to your current project, it's a simple 2 step process:

```
yarn add bs-platform --dev --exact
# or npm
npm install bs-platform -D -S
```

Add the appropriate script tags to package.json:

```json
"scripts": {
"re:build": "bsb -make-world -clean-world",
"re:watch": "bsb -make-world -clean-world -w"
}
```

Copy the `bsconfig.json` file from our docs located [here](https://reasonml.github.io/reason-react/docs/en/installation#adding-reason-to-an-existing-reactjs-project-create-react-app-nextjs-etc)

Then add some files somewhere (don't forget to change `bsconfig.json`, if needed).

## Using Your Favorite Javascript Libraries

The same way that TypeScript has `type annotations`, we have `bindings`. Bindings are libraries that allow you to import a popular project (like lodash) or to import your own local file. ReasonReact is in fact an example of a binding!

## Documentation

See https://reasonml.github.io/reason-react/
See [https://reasonml.github.io/reason-react](https://reasonml.github.io/reason-react)

## Contribute

We welcome all contributors! Anything from docs to issues to pull requests. Please help us :smile:

```sh
git clone https://github.com/reasonml/reason-react.git
cd reason-react
npm install
npm start
```

Then add some files somewhere (don't forget to change `bsconfig.json`, if needed).

See the README inside `src` for more info!

## Editor Support

Looking for syntax highlighting for your favorite editor? Check out [ReasonML Editor Plugins](https://reasonml.github.io/docs/en/editor-plugins)

## Friends of ReasonReact

- [genType](https://github.com/cristianoc/genType) - genType automatically generates bindings for your TypeScript / vanilla JS code.
- [reason-react-native](https://github.com/reason-react-native/reason-react-native) - ReasonML / Bucklescript bindings for React Native. Allows you to use Reason to build an iOS, Android or Web app!
- [reasonml.org](https://reasonml.org/) - An effort by the Reason Association to improve documentation for ReasonML & BuckleScript
- [redex.github.io](https://redex.github.io/) - Find bindings for your favorite libraries here
- [ReasonTown Podcast](https://anchor.fm/reason-town) - ReasonML Podcast
- [ReasonConf Youtube](https://www.youtube.com/channel/UCtFP_Hn5nIbZY4Xi47qfHhw/videos) Reason Conf on Youtube
8 changes: 3 additions & 5 deletions bsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
/* This is the BuckleScript configuration file. Note that this is a comment;
BuckleScript comes with a JSON parser that supports comments and trailing
comma. If this screws with your editor highlighting, please tell us by filing
an issue! */
{
"name" : "reason-react",
"name": "reason-react",
"sources": "src",
"package-specs": [{ "module": "es6", "in-source": true }],
"suffix": ".bs.js",
"refmt": 3,
"bsc-flags": ["-bs-no-version-header"]
}
2 changes: 1 addition & 1 deletion docs/intro-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ ReactDOMRe.renderToElementWithId(<Greeting name="John" />, "root");
This is how you used to write this in plain Javascript (index.js):
```js
/* file: index.js */
ReactDOM.render(<Greeting name="John"> document.getElementById("root"));
ReactDOM.render(<Greeting name="John">, document.getElementById("root"));
```

### Using Greeting in an existing Javascript/Typescript App
Expand Down
6 changes: 5 additions & 1 deletion docs/simple.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ title: A List of Simple Examples

### A Basic Greeting Component

Reason's returns are implicit so you don't need to write `return`, it'll be the last item in the block:
**Some things to note**:

- Reason's `return` statements are implicit so you don't need to write `return`. It'll always be the last item in the block
- Reason has labelled parameters (arguments) that are prefixed by a tilde, eg: `~message`
- Since everything in ReasonReact is typed, we need to wrap our message in `React.string(message)`

```reason
/* Greeting.re */
Expand Down
82 changes: 82 additions & 0 deletions docs/tailwind-css.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: Styling: Tailwind CSS
---

[Tailwind CSS](https://tailwindcss.com) is a new CSS framework that is rapidly
growing in popularity. It's completely customizable and lightweight, making it
a perfect companion to React. If you're not familiar with Tailwind, we recommend
checking out [their docs](https://tailwindcss.com/#what-is-tailwind) for
a gentle introduction before moving forward.

## Setting up Tailwind

Now let's see how we can use Tailwind within ReasonReact and start building an
app!

First, you'll need to create a new ReasonReact project -- we recommend [this
template](https://github.com/bodhish/create-reason-react-tailwind) (select the
`tailwind-starter` option) which has Tailwind set up out of the box. Once you've
installed the dependencies with `yarn install` or `npm install`, you should be
ready to go.

Let's see an example of a React component using Tailwind:

```reason
[@react.component]
let make = () =>
<div className="h-screen flex justify-center items-center">
<div className="max-w-sm rounded overflow-hidden shadow-lg p-4">
<img className="w-full" src=logo alt="Sunset in the mountains" />
<div className="px-6 py-4">
<div className="font-bold text-xl mb-2"> {React.string("Tailwind")} </div>
<p className="text-gray-700 text-base">
{React.string("A reason react starter with tailwind")}
</p>
</div>
</div>
</div>;
```

which gives us the following UI:

<img src="/reason-react/img/tailwind-example.png">

## tailwind-ppx

Often times when you're writing with Tailwind and ReasonReact, you may find
yourself wondering why the UI isn't working like it should, only to find out you
had a typo in a class name. For example,

```reason
<div className="flex flex-ro">
...
</div>
```

Wouldn't it be nice to get some validation _while_ you're writing the Tailwind
classes? Better yet, how about preventing your code from even compiling if the
classes aren't correct? Well, enter
[`tailwind-ppx`](https://github.com/dylanirlbeck/tailwind-ppx): a compile-time
validator for Tailwind CSS. Using this PPX, you can get immediate compiler
errors if you happen to misspell class names, along with a nice suggestion of
what you may have meant to write!

```reason
<div className=[%tw "flex flex-ro"]> /* ERROR: Class name not found: flex-ro. Did you mean flex-row? */
...
</div>
```

Moreover, in a large codebase where components may have many class names, you
may find yourself duplicating some class names. `tailwind-ppx` solves this
issue, too!

```reason
<div className=[%tw "flex flex-row mt-2 pb-3 flex"]> /* ERROR: Duplicate class name: flex */
...
</div>
```

Wrapping the class names in a PPX allows for some powerful integrations with
Tailwind in addition to validation. For more information, check out
`tailwind-ppx`'s [other features](https://github.com/dylanirlbeck/tailwind-ppx#features)
7 changes: 6 additions & 1 deletion docs/use-state-use-effect.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ let make = (~label, ~onSubmit) => {
<input
onBlur=onCancel
onFocus
onChange={event => onChange(ReactEvent.Form.target(event)##value)}
onChange={
event => {
let value = ReactEvent.Form.target(event)##value;
onChange(_ => value)
}
}
value
/>
</form>;
Expand Down
75 changes: 75 additions & 0 deletions docs/usestate-event-value.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
title: Using Event Values With useState
---

In ReactJS, it's common to update a component's state based on an event's
value. Because ReasonReact's `useState` is slightly different than ReactJS,
directly translating JavaScript components to Reason can lead to a common bug.

```js
/* App.js */
function App() {
const [name, setName] = React.useState("John");
return (
<input
type="text"
value={name}
onChange={(event) => setName(event.target.value)}
/>
);
}
```

If we convert this component to reason, we may attempt to write this:

```reason
/* App.re */
/* WRONG! Don't do this! */
[@react.component]
let make = () => {
let (name, setName) = React.useState(() => "John");
<input
type_="text"
value={name}
onChange={event => setName(_ => ReactEvent.Form.target(event)##value)
/>;
};
```

Can you spot the bug?

In the Reason version, the `onChange` callback won't correctly update the state.
This happens because the callback passed to `setName` is run *after* the `event`
variable is cleaned up by React, so the `value` field won't exist when it's
needed.

This isn't actually any different than how events and `useState` hooks work in
ReactJS when you choose to use a callback with `setName`. The only difference
is that ReasonReact enforces that we always use callbacks.

## Solution

Fortunately, fixing this bug is simple:

```reason
/* App.re */
/* CORRECT! This code is bug-free. 👍 */
[@react.component]
let make = () => {
let (name, setName) = React.useState(() => "John");
<input
type_="text"
value={name}
onChange={
event => {
let value = ReactEvent.Form.target(event)##value;
setName(_ => value)
}
}
/>;
};
```

The key is to extract the `value` from the `event` *before* we send it to
`setName`. Even if React cleans up the event, we don't lose access to the
value we need.
15 changes: 8 additions & 7 deletions docs/what-and-why.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
title: What & Why
---

ReasonReact is a safer, simpler way to build [React](https://reactjs.org/) components, in [Reason](http://reasonml.github.io/).
ReasonReact helps you use [Reason](http://reasonml.github.io/) to build [React](https://reactjs.org/) components with deeply integrated, strong, static type safety.

By leveraging the latter's great type system, expressive language features and smooth interoperability with JS, ReasonReact packs ReactJS' features into an API that is:
It is designed and built by people using Reason and React in large, mission critical production React codebases.

- Safe and statically typed
- Simple and lean
- Familiar and easy to insert into an existing ReactJS codebase
- Well thought-out (made by the creator of ReactJS himself!)
ReasonReact uses Reason's expressive language features, along with smooth JavaScript interop to provide a React API that is:

It is often said that writing ReactJS code feels like "just using JavaScript". The same applies to ReasonReact, but we push it further; writing routing, data management, component composition and components themselves feel like "just using Reason".
- Safe and statically typed (with full type inference).
- Simple and lean.
- Familiar and easy to insert into an existing ReactJS codebase.

One of ReactJS's strengths is that it uses the programming language's features to implement framework features. It is often said that ReactJS feels like an extension of the programming language. ReasonReact pushes that philosophy further because the Reason syntax and language features are a better match for React programming patterns. ReasonReact also uses built-in language features to seamlessly integrate into other UI framework patterns left unaddressed by ReactJS. Routing, data management, component composition and components themselves all feel like "just using Reason".
22 changes: 0 additions & 22 deletions lib/js/src/React.js

This file was deleted.

0 comments on commit f2ee693

Please sign in to comment.