Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Updates to Installation, Intro, Additional Examples & Recipes #534

Merged
merged 14 commits into from
Apr 27, 2020
22 changes: 22 additions & 0 deletions docs/adding-data-props.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: Adding data-* attributes
---

Reason doesn't support using props with dashes right now, ie: `data-id` or `data-whatever`. You can overcome this by creating a `Spread` component:

```reason
/* Spread.re */
[@react.component]
let make = (~props, ~children) => ReasonReact.cloneElement(children, ~props, [||]);
```

Using Spread:

```reason
[@react.component]
let make = () =>
<Spread props={"data-cy": name}>
/* This div will now have the `data-cy` attribute in the DOM! */
<div />
</Spread>;
```
6 changes: 5 additions & 1 deletion docs/gentype.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ title: Gentype & Typescript

[Gentype](https://github.com/cristianoc/genType) is a library that automatically generates idiomatic bindings between Reason and JavaScript: either vanilla or typed with TypeScript/FlowType.

If all your components are written in Typescript for example, this is a great way of supporting full type safety in both directions.

Installing it includes running `yarn add --dev gentype` and creating a basic `gentypeconfig` in your `bsconfig.json` file:

```
Expand All @@ -22,7 +24,9 @@ Read more [here](https://github.com/cristianoc/genType#installation)
### Basic Greeting Component

```reason
[@gentype "Greeting"]
/* Greeting.re */

[@genType]
[@react.component]
let make = (~message) => {
<div>{React.string(message)}</div>
Expand Down
28 changes: 21 additions & 7 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,31 @@ title: Installation

## BuckleScript

[BuckleScript](http://bucklescript.github.io/) compiles ReasonML code to JavaScript. You can get it with:
[BuckleScript](http://bucklescript.github.io/) is the tool that compiles ReasonML code 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. You can install it globally or keep it project specific by adding it as a `devDependency`.

### Using Bucklescript init

BuckleScript's [bsb](https://bucklescript.github.io/docs/en/build-overview.html) build system has an `init` command that generates a project template. The `react-hooks` theme happens to be our official, lightweight template optimized for low learning overhead and ease of integration into an existing project.

The `.re` files compile to straightforward `.bs.js` files. You can open `index.html` directly from the file system. No server needed! Change any `.re` file to see that page automatically refreshed.

```sh
# you can use yarn too (yarn global add bs-platform)
npm install --global bs-platform

# creates project folder
bsb -init my-react-app -theme react-hooks

# cd into that folder, npm install, start
cd my-react-app && npm install && npm start

# in another tab
npm run server
```

BuckleScript's [bsb](https://bucklescript.github.io/docs/en/build-overview.html) build system has an `init` command that generates a project template. The `react-hooks` theme happens to be our official, lightweight template optimized for low learning overhead and ease of integration into an existing project.

The `.re` files compile to straightforward `.bs.js` files. You can open `index.html` directly from the file system. No server needed! Change any `.re` file to see that page automatically refreshed.
### Adding Reason to an existing React.js Project (Create React App, Next.js, etc.)

## Adding Reason + Bucklescript to an existing project
Set up is very straight forward! Install two dependencies, add some scripts and create a bsconfig.json file.

Install the following dependencies:

Expand All @@ -29,7 +39,7 @@ yarn add bs-platform --dev --exact
yarn add reason-react --exact
```

Add scripts to package.json:
Add scripts to `package.json`:

```json
"scripts": {
Expand All @@ -38,7 +48,7 @@ Add scripts to package.json:
}
```

Create a bsconfig.json file in the root of your project with the following. You can change the name.
Create a `bsconfig.json` file in the root of your project with the following. All the settings are already defaults, most of this is boilerplate. The important fields are `name`, `bs-dependencies` and `ppx-flags`. As you can see, we've added `reason-react`. This tells Reason where to look for bindings (similar to depdencies in your package.json).

```json
{
Expand Down Expand Up @@ -66,3 +76,7 @@ Create a bsconfig.json file in the root of your project with the following. You
"refmt": 3
}
```

That's it!

**Note**: You'll have to run the reason compiler in a separate terminal. First start your project `yarn start` and in a separate terminal run: `yarn re:watch`
31 changes: 28 additions & 3 deletions docs/intro-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,37 @@ let make = (~name) =>
<button> {ReasonReact.string("Hello " ++ name ++ "!")} </button>;
```

## A usage of the component
## Using Greeting in your App

(assuming there's a `div` on the page with id `greeting`)
If you're writing your entire React app in Reason, you'll probably have a `ReactDOM.render` in an index.js. This is what that looks like in Reason:

```reason
/* file: Index.re */
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"));
```

### Using Greeting in an existing Javascript/Typescript App

ReactDOMRe.renderToElementWithId(<Greeting name="John" />, "greeting");
It's easy to import a Reason component into your existing app. All Reason extensions will have `bs` and export your component as `make`. You can rename it and call it as you usually do. [Gentype](https://github.com/cristianoc/genType) makes this easier (see the example).

```js
/* file: App.js */

import { make as Greeting } from './Greeting.bs'

export default function App() {
return (
<div>
<Greeting name="Peter" />
</div>
)
}
```

Make sure you check out [Examples](simple) for more!
17 changes: 10 additions & 7 deletions docs/simple.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: Simple Examples
title: A List of Simple Examples
---

### A Simple Component
### 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:

Expand All @@ -13,13 +13,16 @@ Reason's returns are implicit so you don't need to write `return`, it'll be the
let make = (~message) => <h1> {React.string(message)} </h1>;
```

Usage in another file:
Usage in another file. Looks very similar to JSX in Javascript!

```reason
ReactDOMRe.renderToElementWithId(
<Greeting message="Hello World!" />,
"index",
);
/* ... */

<div>
<Greeting message="Hello World!">
</div>

/* ... */
```

### A Component with Optional Arguments and React.Fragment
Expand Down
73 changes: 73 additions & 0 deletions docs/working-with-optional-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: Working with Optional Data
---

If you're coming from Javascript, optional data can be a real pain in the butt. ReasonML removes a *whole class* of `null` and `undefined` bugs which makes your code WAY safer and easier to write, but it takes some good examples to get you there :smile:

### Accessing Optional Nested Data

Say you have have an array of colors and you want to match one of those colors:

```reason
let selected = colors->Belt.Array.getBy(c => c##id === id);
```

```javascript
// Javascript
const selected = colors.find(c => c.id === id);
```

In both cases `selected` could be optional. The compiler may yell at you to handle that case, here's how you could handle it:

```reason
let label = selected->Belt.Option.mapWithDefault(
"Select a Color",
selected => selected##name
);
```

What this is doing: "if selected exists, go look into `selected##name` otherwise return `Select a Color`".

Read more about [`mapWithDefault`](https://reasonml.org/apis/javascript/latest/belt/option) here.

### Something or Nothing

We need to grab the name of the person, but we also know that `name` can come back as `undefined`. We still want that label to be a string.

```reason
/* create the type for the record, totally ok that it's the same name! */

type person = {
name: option(string)
};

let person = {
name: None
};

let label = switch(person.name) {
| Some(name) => name
| None => "Peter"
}
```

You can also use `Belt.Optional.getWithDefault` which is sugar for above:

```reason
let label = Belt.Option.getWithDefault(person.name, "Peter");
```

If you need to return null instead of a component:

```
<div>
{
switch (person.name) {
| Some(name) => <Name name="Peter" />
| None => React.null
}
}
</div>;
```

Read more about [`getWithDefault`](https://reasonml.org/apis/javascript/latest/belt/option) here.
12 changes: 9 additions & 3 deletions website/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"previous": "Previous",
"tagline": "All your ReactJS knowledge, codified.",
"docs": {
"adding-data-props": {
"title": "Adding data-* attributes"
},
"callback-handlers": {
"title": "Callback Handlers"
},
Expand Down Expand Up @@ -129,7 +132,7 @@
"title": "send/handle callbacks having Incompatible Types"
},
"simple": {
"title": "Simple Examples"
"title": "A List of Simple Examples"
},
"state-actions-reducer": {
"title": "State, Actions & Reducer"
Expand Down Expand Up @@ -160,6 +163,9 @@
},
"what-and-why": {
"title": "What & Why"
},
"working-with-optional-data": {
"title": "Working with Optional Data"
}
},
"links": {
Expand All @@ -176,7 +182,7 @@
"ReactJS Idioms Equivalents": "ReactJS Idioms Equivalents",
"Record API (deprecated)": "Record API (deprecated)",
"FAQ": "FAQ",
"Code Snippets": "Code Snippets",
"Recipes & Snippets": "Recipes & Snippets",
"Community": "Community",
"Try": "Try"
}
Expand All @@ -192,14 +198,14 @@
"Need help?|no description given": "Need help?",
"This project is maintained by a dedicated group of people.|statement made to reader": "This project is maintained by a dedicated group of people.",
"Get Started|no description given": "Get Started",
"Examples|no description given": "Examples",
"It's Just React|no description given": "It's Just React",
"Just a bunch of zero-runtime type definitions and lightweight utilities, for the same React you've come to know.|no description given": "Just a bunch of zero-runtime type definitions and lightweight utilities, for the same React you've come to know.",
"Safe and Sound|no description given": "Safe and Sound",
"Simple, solid and inferred using Reason types. Write the same React code, get your type system guarantees automatically.|no description given": "Simple, solid and inferred using Reason types. Write the same React code, get your type system guarantees automatically.",
"Drop In|no description given": "Drop In",
"Powered by ReactJS under the hood. Freely integrate your existing React libraries and knowledge.|no description given": "Powered by ReactJS under the hood. Freely integrate your existing React libraries and knowledge.",
"QuickStart|no description given": "QuickStart",
"Examples|no description given": "Examples",
"Projects Using ReasonReact|no description given": "Projects Using ReasonReact",
"See Full List|no description given": "See Full List",
"Help Translate|recruit community translators for your project": "Help Translate",
Expand Down
8 changes: 8 additions & 0 deletions website/pages/en/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ class HomeSplash extends React.Component {
>
<translate>Get Started</translate>
</Button>
<Button
className="getStarted"
href={
siteConfig.baseUrl + "docs/" + this.props.language + "/simple"
}
>
<translate>Examples</translate>
</Button>
</div>
</div>
</div>;
Expand Down
4 changes: 3 additions & 1 deletion website/sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@
]
},
"examples": {
"Code Snippets": [
"Recipes & Snippets": [
"simple",
"usestate-hook",
"usereducer-hook",
"useeffect-hook",
"use-state-use-effect",
"usedebounce-custom-hook",
"adding-data-props",
"working-with-optional-data",
"render-props",
"importing-js-into-reason",
"importing-reason-into-js",
Expand Down