React 入門

# Reactの事始め

## 経緯

つい、3ヶ月くらい前までがしがし_Mobx_ × _React_ かいてたけど、激動すぎてはじめてすぎて書き方を忘れたため、Reactから入門しようと思ったため。ほぼ、日記。

## Contents
- Cli(create-react-app)のインストール
- [React](https://reactjs.org/)のページの最初の問題の対応

## Cliのインストール

Angular、nuxtほど強くはないが、ってかReactっぽいViewベースのCliのインストール。(...スキャホールドないのかな。)

### Yarnの場合

```terminal
$ yarn add create-react-app
$ create-react-app my-project && cd my-project
$ yarn start
```

### Npmの場合
```terminal
$ npm install -g create-react-app
$ create-react-app my-project && cd my-project
$ npm start
```

### Npx

```terminal
$ npx create-react-app my-app
$ cd my-app
$ npm start
```

### Tree

```terminal
$ pwd #project_path
$ tree .
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   └── favicon.ico
│   └── index.html
│   └── manifest.json
└── src
    └── App.css
    └── App.js
    └── App.test.js
    └── index.css
    └── index.js
    └── logo.svg
    └── registerServiceWorker.js
```

## Reactのページにあるサンプル

### A Simple Component

<img width="1438" alt="A-Simple-Component.png" src="https://qiita-image-store.s3.amazonaws.com/0/144543/703c498a-82cc-c80c-5476-e3a805a93ce0.png">

はまるところがない。一応、
PureComponentでもいいよなと思いながら、下で実装。

```jsx:ASimpleComponent.js
import React, { Component } from "react";

export class HelloMessage extends Component {
  render() {
    const { name } = this.props;
    return <div>Hello {name}</div>;
  }
}

```

### A Stateful Component

<img width="1440" alt="A-Stateful-Component.png" src="https://qiita-image-store.s3.amazonaws.com/0/144543/2c1c83f0-0e2e-784a-e0c9-9cba6c6aee9a.png">

まだ、はまらない。なんとなくこんな書き方だっけでいけた。

```binding.js
this.method_name = this.method_name.bind(this)
```

については、アロー関数でbindすればほぼ同じ書き方でいけることを思い出した。

```jsx:AStatefulComponent.js
import React, { Component } from 'react';

export class Timer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      seconds: 0,
    }
  }
  tick() {
    this.setState((prevState) => ({
      seconds: prevState.seconds + 1
    }))
  }
  componentDidMount() {
    this.timer = setInterval(() => this.tick(), 1000);
  }
  componentWillUnMount() {
    clearInterval(this.timer);
  }
  render() {
    const { seconds } = this.state;
    return (
      <div><p>Second: {seconds}</p></div>
    );
  }
}
```

### An Application

<img width="1440" alt="An-Application.png" src="https://qiita-image-store.s3.amazonaws.com/0/144543/e4ec7376-2588-4eda-aaf2-250cd2d74c1a.png">

はまった。Reactっていうより、Objectの参照ではまった。

```bad.js
changeHandler($ev) {
  this.setState(prevState => ({
    value: $ev.target.value, // null
  }))
}
```

結果、いらないものまでつけてた。
このPropsとかで分離しにくいのがいやで、MobxかRedux使いたいって速攻思い出した。

```jsx:TodoApp.js
import React, { Component } from 'react';

export const TodoList = ({ todoList, markAsComplete, removeTodo}) => (
  <ul>
    {todoList.map((todo) => {
      const style = todo.isCompleted ? { textDecoration: 'line-through' } : {};
      return (
        <li key={todo.id} style={style}>
          <input type="checkbox" value={todo.isCompleted} onChange={($ev) => markAsComplete($ev, todo.id)}/>
          <span>{todo.text}</span>
          <button type="button" onClick={($ev) => removeTodo($ev, todo.id)}>remove</button>
        </li>
      )})
    }
  </ul>
)

export class TodoApp extends Component {
  constructor(params) {
    super(params);
    this.state = {
      todoList: [],
      text: '',
    }
  }
  submitHandler = ($ev) => {
    $ev.preventDefault();
    if (!this.state.text.length) {
      return;
    }
    const newItem = {
      text: this.state.text,
      id: Date.now(),
      isCompleted: false,
    };
    this.setState(prevState => ({
      items: prevState.todoList.push(newItem),
      text: '',
    }));
  }
  handleChange = ($ev) => {
    const value = $ev.target.value;
    this.setState({ text: value})
  }
  markAsComplete = ($ev, todoId) => {
    const target = $ev.target;
    const value = target.value;
    this.setState(prevState => ({
      todoList: prevState.todoList.map((todo) => {
        if(todo.id !== todoId) { return todo; }
        todo.isCompleted = value;
        return todo;
      })
    }))
  }
  removeTodo = ($ev, todoId) => {
    this.setState(prevState => ({
      todoList: prevState.todoList.filter(todo => (todo.id !== todoId))
    }))
  }
  render() {
    const { todoList, text } = this.state;
    const { submitHandler, handleChange, markAsComplete, removeTodo } = this;
    return (
      <div>
        <h3>TODO</h3>
        <TodoList removeTodo={removeTodo} todoList={todoList} markAsComplete={markAsComplete}/>
        <form onSubmit={submitHandler}>
          <input type="text" value={text} onChange={handleChange}/>
          <button type="submit">ADD TODO {todoList.length + 1}</button>
        </form>
      </div>
    );
  }
}
```

### A Component Using External Plugins

昔お世話になったなーとおもいながら、[Remarkable](https://www.npmjs.com/package/remarkable)をインストール。

```console
$ yarn add remarkable
$ yarn start
```

<img width="1440" alt="A-Component-Using^External Plugins.png" src="https://qiita-image-store.s3.amazonaws.com/0/144543/eff08a3c-8dfb-4e2c-a286-e9eb0d7cc65c.png">

```jsx:MarkdownEditor.js
import React, { Component } from "react";
import Remarkable from "remarkable";

const MD = new Remarkable();

export class MarkdownEditor extends Component {
  constructor(props) {
    super(props);
    this.state = { value: "Hello, **world**!" };
  }
  handleChange = $ev => {
    const target = $ev.target;
    const value = target.value;
    this.setState(() => ({
      value
    }));
  };
  get getRawMarkup() {
    return { __html: MD.render(this.state.value) };
  }
  render() {
    const { handleChange, getRawMarkup } = this;
    const { value } = this.state;
    return (
      <div className="MarkdownEditor">
        <h3>Input</h3>
        <label htmlFor="markdown-content">Enter some markdown</label>
        <textarea
          id="markdown-content"
          onChange={handleChange}
          defaultValue={value}
        />
        <h3>Output</h3>
        <div className="content" dangerouslySetInnerHTML={getRawMarkup} />
      </div>
    );
  }
}

```

このgetterの書き方いけるのか不安。

### 終わってから。

結構、書き方忘れてることに気づいた。
やばいので、だれか副業くださいリモートで。という気持ちに苛まれた。


##### 最終的なディレクトリ

きがむいたらかく気がしたので、exportようのファイルを作成しました。
Reactの時は、プロジェクトで共通componentが作りながらの実装だったため、切り離しやすいように

```
feature_directory
  |- index.js # export用のfile
  |- component_a[.b,.c].js # component層のみで基本的にmethodかかない+styledComponentで作成
  |- const.js # たまに使ってた。flow導入してからは、model.js的にしようとしてたきがする。
```
みたいなclass component -> funtional componentをimport側は意識しないでとれるように実装してたきがします(あんまり覚えてない)。

でindex.jsをimport用のlibraryにして読み込ませることを考えてました。
今回でいうと以下になりましたー。
俺のコードの方が綺麗とかあったら、ください!!
速攻、ゴマすります。

```index.js
export * from "./HelloMessage";
export * from "./Timer";
export * from "./TodoApp";
export * from "./MarkdownEditor";
```