Reactを学んだ(1) ~StateとProps~

# Reactの特徴

- Compositional
- Declarative code
    - いちいちいちいち処理の詳細まで書かない
    - (e.g.) `const longNames = people.filter(name => name.length > 6)` 
    - (c.f.) Imperative code ではない

- Unidirectional Dataflowを使う
    - dataflowはparent elementからchildrenの一方向に伝搬される
    - 子は親の持つデータを参照できる。子は親のデータを変更しようと思ったらその旨を親に伝え、親がそれをデータの変更を行う
    - Data-Binding ではない
    - Data-Bindingを使うと、appのどこからでも保持していたデータを変更できる


# Reactでelementを作る

- `React.createElement( <tag name>, <propsのhash(=オブジェクト)>, <content in tag> );`で、仮想DOMを初期化。
    -  e.g. `const element = React.createElement('div', null, 'My name is Tyler, and I love porcupines.');`
    -  creteElementしただけでは、描画されない。これを、`ReactDOM.render(element), document.getElementById('root')`とかして、DOMに反映する。
    -  propsにはhashを渡す。有効なキーは`className`とか`htmlFor`とか。
        -  DOM要素では、ある要素のclassにアクセスするには、`cName = elementNodeReference.className;`とするから。

## Reactでネストしたelementを作る方法

```js

import React from 'react'
import ReactDOM from 'react-dom'

const people = [
  { name: "John", id: 0 },
  { name: "Paul", id: 1 }
]

const element = React.createElement('ol', null,
  people.map((person) => (
    // 子要素を配列にする時は、propsがそれぞれの要素でユニークなkeyを持っていないと怒られる
    React.createElement('li', {key: people.id}, person.name)
  ))
)

ReactDOM.render(
  element,
  document.getElementById('root')
)
```

-  JSX(=syntax extention for JS)という拡張構文を使うことで、上記のコードもHTMLチックに、楽に書ける。

```js

// 上記のcreateElementの箇所をJSXで書き換えると、
const element = <ol>
  {people.map((person) => (
    <li key={person.id}>{person.name}</li>
  ))}
</ol>

```

## Class ComponentとStateless Functional Component


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/e006db1a-1cda-4cd1-da16-8bda702af161.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/05c92121-0f58-84d4-00e3-70158dabc9c4.png)


## 作ったReact componentクラスをexportする方法

```js
export default ListContacts
```

## 初期化時にstateをプロパティーとしてComponentに持たせる方法

```js
class User extends React.Component {
 constructor(props) {
   super(props);
   this.state = {
     username: 'Tyler'
   };
 }
}
```

Babelでトランスコンパイルするなら以下でもいける。

```js
class User extends React.Component {
 state = {
   username: 'Tyler'
 } 
}
```

- Avoid initializing that state with props! (e.g. `this.state = {user: props.user}`)

## stateの更新

- `this.state.hoge = new_hoge`という風に更新しても、re-renderingされない。
- 引数の関数の返り値が元のstateにマージされる。

```js

this.setState((prevState) => (
  {count: prevState.count + 1}
)
```
- なお、元のstateの値を使う必要がないなら、引数にハッシュを渡せばいい。

```js
this.setState({ count: 2 })
```

## stateの型チェック

- `yarn add prop-types` でprop-typesというパッケージをインストールして以下のように使う。

```js
ListContacts.propTypes = {
  contacts: PropTypes.array.isRequired,
  onDeleteContact: PropTypes.func.isRequired,
}
```

- Componentを定義したクラス内で定義するには、

```js
static propTypes = {
  contacts: PropTypes.array.isRequired,
  onDeleteContact: PropTypes.func.isRequired,
}
```

## form component

- フォームに打ち込んだ値をそのままフォームのvalueにするのではなく、一旦stateに収納して、それをsource of truthとして使う。

```jsx

const { query } = this.state　 // state.queryをqueryに取り出して、

updateQuery(query) {
  this.setState(() => ({
    query: query.trim()     // valueがqueryというstateに収納される
  }))
}

render() {(
  <input
    className='search-contacts'
    type='text'
    placeholder='Search Contacts!'
    value={query}
    onChange={(event) => this.updateQuery(event.target.value)}  // evnt.target.valueで入力値が取れる
  />
)}
```

- 以下にちょっとハマった。

```jsx

<form onSubmit={(event) => {                //////  onSubmit()はeventを引数にとる関数を渡す
    event.preventDefault();                 //////　書かなかいと、画面がrefreshされてstateが初期値に戻った...
    this.props.addItem(this.state.value)
}}>
</form>
```



# yarnコマンド

```
  yarn start
    Starts the development server.

  yarn build
    Bundles the app into static files for production.

  yarn test
    Starts the test runner.

  yarn eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!
```