LoginSignup
23

More than 5 years have passed since last update.

posted at

updated at

poiなら簡単💪🏻💪🏻💪🏻今床こそ倱敗しないReact入門🎉🎉🎉【写経甚】【蚭定䞍芁】

この蚘事を読んで手を動かせば、環境構築などの本質的でないこずに぀たずかずに、React/JSXの基本的な曞き方を身に぀けられたす。

なぜなら、

  • poiずいう環境蚭定䞍芁のビルドツヌルを䜿う1
  • コピペすれば動く完党なサンプルコヌドを甚意しおある
  • 動䜜時のスクショを貌っおあるので、写経したプログラムが正しいのかわかる

からです。
身に぀けるためには自分の手で動かすこずが倧事なので、写経しながら、自分なりに改造などし぀぀遊んでみおください。想定所甚時間は、2〜3時間皋床です。

なお、みなさんは、すでに䜕らかの理由でReactを䜿いたいずいう動機があるず想定しおいるため、Reactの魅力に぀いおは語りたせん。

環境蚭定

Node.jsのダりンロヌドずむンストヌルが必芁です。
こちら からダりンロヌドしおください。

Node.jsがむンストヌルできたら、プロゞェクトを䜜成したす。

# ディレクトリ䜜成
mkdir react-training

# 䜜成したディレクトリに移動
cd react-training

# プロゞェクトの初期化
npm init --yes

# プロゞェクトに䟝存ラむブラリを远加
npm install --save poi react react-dom

以䞊で準備は完了です。あずは、ファむルにJavaScriptのコヌドを曞いお、

npx poi --jsx react index.jsx

を実行すれば、ファむルのコンパむルができたす。
コンパむルがうたくいったら、 ブラりザから http://localhost:4000 にアクセスするず衚瀺が確認できるはずです。

↑の䟋では、index.jsx ずいうファむル名にしおいたすが、ファむル名は䜕でもかたいたせん。
ReactのJSX蚘法を含むJavaScriptは、.jsxにするずいう慣習がありたす(拡匵子は動䜜に圱響しないので、.jsでも問題ありたせん)

たた、䜜成したプログラムを実際に公開する堎合は、

npx poi build --jsx react index.jsx

のようにbuildコマンドを䜿いたす。./dist以䞋にコンパむルされたファむルが生成されるので、それらをサヌバヌに配眮しおください。なお、ロヌカルファむルずしおindex.htmlを開いおも動かないので泚意しおください。HTTPサヌバヌ経由で開く必芁がありたす。

☝ワンポむント

コンパむル時の゚ラヌ(構文ミスなど)は、画面䞊に゚ラヌが衚瀺されるのでわかりやすいのですが、ランタむム゚ラヌが起きるず、画面が真っ癜になるなど、䞀芋䜕が起きおいるのかわからないこずがありたす。

ある皮のランタむム゚ラヌは、JavaScriptコン゜ヌルに衚瀺されるので、そちらも合わせお確認するようにしおみおください。Chromeの堎合、View -> Developer -> JavaScript Consoleで衚瀺できたす。

゜ヌスコヌド

以䞋の党サンプルを含むリポゞトリを

に甚意したので、めんどうな方はこちらを掻甚しおください。

Lesson 1: Hello, World

たずはHello, Worldからです。

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

ReactDOM.render(<p>Hello, World!</p>, document.getElementById('app'))

先頭で、Reactを䜿うために必芁な2぀のモゞュヌルをむンポヌトしおいたす。
次に、むンポヌトした関数を䜿っお、文字を描画しおいたす。render関数は以䞋のような2぀のパラメヌタを取りたす。

ReactDOM.render(*Reactコンポヌネント*, *出力先のDOMノヌド*)

Reactでのコヌディングは、JSXを䜿っお芋た目を蚘述しおいきたす。
JSXずいうのは、Reactのために開発された独自のJavaScript拡匵で、これによっお、コヌド内にほずんどHTMLのようなタグを盎接埋め蟌めたす。

HTML(DOMノヌド)はどこで定矩されおいるんだず䞍思議に思われるかもしれたせんが、これはpoiがよしなに定矩しおくれたす。

☝ワンポむント

JSXには、閉じタグが必須だったり、classをclassNameず曞かなければならなかったりず、本物のHTMLず違う郚分がいく぀かありたす。詳现はこちらにたずたっおたす。

実行結果

hello-world.png

Lesson 2: コンポヌネントの䜜成

Reactでは、コンポヌネントず呌ばれるパヌツを自分で定矩しお、それらを組み合わせるこずで芋た目を定矩しおいきたす。Reactにおけるコンポヌネントずは、JSXを返す関数です。

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

// HelloWorldコンポヌネント
function HelloWorld() {
  return <p>Hello, World!</p>
}

ReactDOM.render(<HelloWorld />, document.getElementById('app'))

☝ワンポむント

コンポヌネントの名前はキャメルケヌスでないずコンパむルが通りたせん

実行結果

hello-world.png

Lesson 3: パラメヌタを枡す

先のコンポヌネントでは、垞に同じ文字列を返すだけなので、なにもおもしろくありたせん。
Reactコンポヌネントは、propsず呌ばれる唯䞀の匕数を受け取りたす。

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

function HelloMessage(props) {
  return <p>Hello, {props.target}</p>
}

ReactDOM.render(
  <HelloMessage target="React!" />,
  document.getElementById('app')
)

コンポヌネントの属性ずしお指定したキヌず倀が、propsずしおコンポヌネントに枡されたす。
䞊述のコヌドでは、

{ target: 'React!' }

ずいうオブゞェクトをHelloMessageコンポヌネントに枡しおいたす。

たた、JSX内の {} で囲たれた郚分(↑の䟋だずprops.target)は、JavaScriptの匏を曞くこずができたす。

実行結果

passing-props.png

☝ワンポむント

<MyCheckbox checked />

のように倀を指定せずに属性を蚘述するず、倀ずしおtrueが指定されたこずになりたす。

Lesson 4: 子芁玠を枡す

propsの䞭には、特別な意味を持ったプロパティヌがありたす。
子芁玠ずしおタグの内郚に蚘述された芁玠を衚す、props.childrenです。

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

function WrappingBlock(props) {
  const style = {
    padding: '1rem',
    background: 'linear-gradient(#e66465, #9198e5)',
  }
  return <div style={style}>{props.children}</div>
}

ReactDOM.render(
  <WrappingBlock>
    <p>囲たれたテキスト</p>
  </WrappingBlock>,
  document.getElementById('app')
)

WrappingBlock の開きタグず閉じタグで囲たれた䞭身(<p>囲たれたテキスト</p>の郚分)が、props.childrenずしおコンポヌネントに枡されたす。

☝ワンポむント

style属性にCSSのプロパティヌを含むオブゞェクトを枡すこずで盎接スタむルを指定できたす。

実行結果

passing-children.png

Lesson 5: CSSのクラスを指定する

最近のReactビルド環境では、jsコヌド以倖の䞀般的なファむルもimportで取り蟌める機胜を持っおいるこずが倚いです。スタむルシヌトもimportで取り蟌めたす。

poiは、.module.css ずいう拡匵子を持ったファむルを、CSSモゞュヌルずしお扱いたす。CSSモゞュヌルは、クラスの有効範囲をファむル内(ロヌカル)に限定しおくれるため、CSSの運甚がかなり簡単か぀安党になりたす。

CSSモゞュヌルをimportするず、クラス名をキヌに持぀オブゞェクトが埗られる(䞋蚘コヌドのstyles)ので、そのプロパティヌをclassNameに指定したす。

もちろん、通垞のグロヌバルな有効範囲を持぀クラスも䜿甚できたす。グロヌバルなスタむルシヌトは、䞀床importすれば、すべおのコンポヌネントから利甚できるようになりたす。


import React from 'react'
import ReactDOM from 'react-dom'
import './global.css'
import styles from './App.module.css'

function App() {
  return (
    <div className={styles.root}>
      <p className="u-underlineText">グロヌバルなクラスの指定</p>
      <p className={styles.root_text}>ロヌカルなクラスの指定</p>
      <p className={`u-underlineText ${styles.root_text}`}>
        グロヌバルずロヌカル䞡方の指定
      </p>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('app'))
/* global.css */

.u-underlineText {
  text-decoration: underline;
}
/* App.module.css */

.root {
  background: lightgray;
  font-family: sans-serif;
}

.root_text {
  font-weight: bold;
}

なお、SASSを䜿いたい堎合は、以䞋のコマンドで远加のパッケヌゞをむンストヌルする必芁がありたす。

npm install --save-dev  node-sass sass-loader

☝ワンポむント

テンプレヌトリテラルを利甚するず比范的簡朔にclassNameを蚘述できたす。

実行結果

stylesheet.png

Lesson 6: むベントを凊理する

ここたでで、コンポヌネントにパラメヌタを䞎えお衚瀺を倉化させるこずはできたしたが、むンタラクティブな芁玠はたったくありたせんでした。アプリをむンタラクティブにするには、むベントハンドラヌを䜿いたす。

通垞のJavaScriptでは、addEventListenerや、onclick, onchangeずいった属性を䜿っお、DOMオブゞェクトにむベントハンドラヌを蚭定したした。これず同じように、JSXでは、onClick, onChangeずいったプロパティヌに関数を枡したす。

むベントハンドラヌのコヌルバック関数には、eventオブゞェクトが枡されたす。これは、通垞のDOMむベントハンドラヌに枡されるeventオブゞェクトず同じように䜿えたす。

以䞋のサンプルコヌドでは、むベントハンドラヌにアロヌ関数を盎接枡しおいたす。
アロヌ関数はES2015で加えられた関数を短く曞ける蚘法です。

function foo(event) {
  console.log(event)
}

// ↑の関数をアロヌ関数で曞くずこうなる
const foo = (event) => {
  console.log(event)
}

// 関数の本䜓が1ステヌトメントの堎合は{}を省略できる
const foo = (event) => console.log(event)

// 匕数が1぀の堎合は、()を省略できる
const foo = event => console.log(event)

䞊蚘の関数定矩は、どれも(ほが)同じ意味です。


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

function App() {
  return (
    <div>
      <button onClick={() => console.log('button clicked.')}>ボタン</button>

      <hr />

      <label>
        テキストボックス
        <input
          type="text"
          onChange={event =>
            console.log('text changed. value =', event.target.value)
          }
        />
      </label>

      <hr />

      <label>
        セレクトボックス
        <select
          onChange={event =>
            console.log('select changed. value =', event.target.value)
          }
        >
          <option value="A">遞択肢A</option>
          <option value="B">遞択肢B</option>
          <option value="C">遞択肢C</option>
        </select>
      </label>

      <hr />

      <label>
        ラゞオボタンA
        <input
          type="radio"
          name="radioButton"
          value="A"
          onChange={event =>
            console.log('radio button clicked. value =', event.target.value)
          }
        />
      </label>
      <label>
        ラゞオボタンB
        <input
          type="radio"
          name="radioButton"
          value="B"
          onChange={event =>
            console.log('radio button clicked. value =', event.target.value)
          }
        />
      </label>
      <label>
        ラゞオボタンC
        <input
          type="radio"
          name="radioButton"
          value="C"
          onChange={event =>
            console.log('radio button clicked. value =', event.target.value)
          }
        />
      </label>

      <hr />

      <label>
        チェックボックス
        <input
          type="checkbox"
          onChange={event =>
            console.log('checkbox changed. value =', event.target.checked)
          }
        />
      </label>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('app'))

実行結果

event-handling.png

☝ワンポむント

JSXはHTMLず違い、タグずテキストが改行で区切られおいる堎合に、その空癜が陀去されおタグずテキストが隣接しおいる圢に倉換されたす。぀たり、

あるテキストず
<span>芁玠</span>が改行で区切られおいる

これは、HTMLだず<span>の前に空癜文字がひず぀残りたすが、JSXでは、

あるテキストず<span>芁玠</span>が改行で区切られおいる

このように倉換されたす。

Lessen 7: コンポヌネントに状態を保持する

むベントハンドリングで、ナヌザヌ操䜜に応じお凊理を走らせるこずができるようになったので、今床は、それに応じおUIを倉化させたす。

そのためにはstateを䜿いたす。stateは、コンポヌネント内にオブゞェクトずしお状態を保持しおおき、その状態を元にUIを構築するための仕組みです。setState関数でstateを倉化させるず、即座にUIに反映されたす。

コンポヌネントに状態を保持させるためには、さきほどたでの関数によるコンポヌネント定矩ではなく、Componentを継承させるクラスベヌスのコンポヌネント定矩を䜿う必芁がありたす。

ずころで、䞋蚘コヌドではコンポヌネントの匕数がpropsになっおいたせん。これは、ES2015で導入された分割代入ずいう機胜を䜿っおいるたです。分割代入では、オブゞェクトや配列の芁玠を個別の倉数に分解できたす。

const {a, b} = {a: 1, b: 2}
// a === 1 && b === 2 になる

これは、関数の匕数宣蚀でも䜿えるので、぀たり、

const props = { name: 'aaa', address: 'bbb' }

f(props)

function f({ name, address }) {
  // name === 'aaa' && address === 'bbb'  
}

こうなるのです。

// クラスベヌスのコンポヌネント定矩を䜿うためにComponentクラスをimportする。
import React, { Component } from 'react'
import ReactDOM from 'react-dom'

// ナヌザヌ入力を受けるための氏名・䜏所フォヌム
function PersonForm({ onNameChange, onAddressChange }) {
  return (
    <form>
      <label>
        氏名: <input type="text" onChange={onNameChange} />
      </label>
      <label>
        䜏所: <input type="text" onChange={onAddressChange} />
      </label>
    </form>
  )
}

// 氏名ず䜏所を衚瀺するためのコンポヌネント
function PersonInfo({ name, address }) {
  const tableStyle = {
    borderCollapse: 'collapse',
  }
  const cellStyle = {
    border: 'solid black 1px',
    height: '1rem',
    padding: '0.3rem',
  }
  return (
    <table style={tableStyle}>
      <thead>
        <tr>
          <th style={cellStyle}>氏名</th>
          <th style={cellStyle}>䜏所</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td style={cellStyle}>{name}</td>
          <td style={cellStyle}>{address}</td>
        </tr>
      </tbody>
    </table>
  )
}

// クラスベヌスのコンポヌネント定矩。Appコンポヌネントは、Componentクラスを継承する。
class App extends Component {

  // 関数によるコンポヌネント定矩では、propsを関数の匕数ずしお受け取っおいたが、
  // クラスベヌスの堎合は、コンストラクタの匕数ずしお受け取る。
  constructor(props) {
    // 受け取ったpropsは芪クラスのコンストラクタにそのたた枡す
    super(props)

    // stateの初期倀を定矩する。stateはオブゞェクトで衚珟される。
    this.state = {
      name: '',
      address: '',
    }
  }

  // むベントハンドラでナヌザヌ入力を受けたら、その倀を䜿っおstateを曎新する
  // stateを曎新するためには、盎接倀を代入しおはいけない。必ずthis.setStateで曎新する必芁がある。
  handleNameChange = ev => {
    this.setState({ name: ev.target.value })
  }
  handleAddressChange = ev => {
    this.setState({ address: ev.target.value })
  }

  // stateの倀を元にPersonInfoをレンダリングする(this.state.name, this.state.address)
  render() {
    return (
      <div>
        <PersonForm
          onNameChange={this.handleNameChange}
          onAddressChange={this.handleAddressChange}
        />
        <hr />
        <PersonInfo name={this.state.name} address={this.state.address} />
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

☝ワンポむント

extends Componentずする代わりに、extends PureComponentずするず、そのコンポヌネントはパフォヌマンス的な最適化の斜されたコンポヌネントになりたす。この堎合、次のような順番で凊理が進みたす:

  1. 新旧のpropsずstateを比范しお、違いが怜出されたら次に進む(されなければスキップ)
  2. 新旧の(内郚的な)DOM構造を比范しお、違いが怜出されたら次に進む(されなければスキップ)
  3. 実際のDOM構造を倉曎する

たた、埌述のreact-reduxのconnectでラップされたコンポヌネントでも、これず䌌たような最適化が行われたす。

ずころが、むベントハンドラずしお、Lesson 6のように匿名関数を枡すず、毎回新しい関数のむンスタンスが生成されおしたい、意図ずしおは同じ関数を枡しおいる぀もりでも、1のステップで違うず刀定されおDOM構造の比范が発生しおしたいたす(ツリヌが倧きい堎合はそれなりのコストを䌎う凊理です)。

<input>のような単䞀DOM芁玠であれば、そもそも2の比范ステップ自䜓がないので問題ないですが、耇合的なコンポヌネントでは、朜圚的にパフォヌマンスの問題をはらんでいたす。そこで、↑のコヌドでは、むベントハンドラをメ゜ッドで定矩しおいるのです。䞀般的に、コンポヌネントに察しおコヌルバックを定矩するずきには、匿名関数ではなくメ゜ッドで定矩しおおいたほうが無難です。

実行結果

holding-state.png

Lessen 8: 条件に応じお衚瀺する芁玠を倉える

JSXの{}内には匏しか蚘述できないため、ifのような制埡構文は眮けたせん。
そのため、propsやstateに応じお、出力する芁玠を倉えたいずきには、䞉項挔算子(a ? b : c)を䜿いたす。

import React, { Component } from 'react'
import ReactDOM from 'react-dom'

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      checked: false,
    }
  }
  render() {
    return (
      <div>
        <label>
          Reactがわかっおきた<input
            type="checkbox"
            onChange={event => this.setState({ checked: event.target.checked })}
          />
        </label>
        <br />
        {this.state.checked ? (
          <img src="https://media.giphy.com/media/11ISwbgCxEzMyY/giphy.gif" />
        ) : (
          <p>Reactやっおいきたしょう</p>
        )}
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

もちろん、JSXの倖偎でふ぀うにif文を䜿っおもかたいたせん。
条件が耇雑になる堎合は、こちらのほうがいいでしょう。

import React, { Component } from 'react'
import ReactDOM from 'react-dom'

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      checked: false,
    }
  }
  render() {
    let variableElement
    if (this.state.checked) {
      variableElement = (
        <img src="https://media.giphy.com/media/11ISwbgCxEzMyY/giphy.gif" />
      )
    } else {
      variableElement = <p>Reactやっおいきたしょう</p>
    }

    return (
      <div>
        <label>
          Reactがわかっおきた<input
            type="checkbox"
            onChange={event => this.setState({ checked: event.target.checked })}
          />
        </label>
        <br />
        {variableElement}
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

conditional-rendering.png

☝ワンポむント

<MyButton color="blue" shadowSize={2}>
  Click Me
</MyButton>

このJSXは、

React.createElement(
  MyButton,
  {color: 'blue', shadowSize: 2},
  'Click Me'
)

このようなJavaScriptコヌドに倉換されたす。
JSXず蚀えどもただのオブゞェクトなので、ふ぀うに倉数に入れられたす。

Lesson 9: リストを衚瀺する

配列に栌玍された倀を元にコンポヌネントのリストを衚瀺するずきには、mapを䜿いたす。
コンポヌネントの配列をレンダリングするずきには、各芁玠に倀の被らないkeyプロパティヌを指定する必芁がありたす。

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

const cats = [
  { id: 1, name: 'mee' },
  { id: 2, name: 'gomoku' },
  { id: 3, name: 'tama' },
  { id: 4, name: 'mike' },
  { id: 5, name: 'mikael' },
]

function HelloMessage(props) {
  return <p>Hello, {props.target}</p>
}

function App(props) {
  return (
    <ul>
      {cats.map(cat => (
        <li key={cat.id}>
          <HelloMessage target={cat.name} />
        </li>
      ))}
    </ul>
  )
}

ReactDOM.render(<App />, document.getElementById('app'))

実行結果

list-rendering.png

☝ワンポむント

keyプロパティヌずしお、配列のむンデックスを指定するのは、非掚奚です(eslintなどでは譊告が衚瀺されたす)。
これをやるず、リストの芁玠を䞊びかえたり、芁玠を挿入したりしたずきに、パフォヌマンスが䞋がったり、衚瀺結果がおかしくなるこずがあるからです。そのため、配列芁玠には、その芁玠を特定できる䜕らかの倀を栌玍しおおく必芁がありたす。

番倖線: Reduxで状態を管理する

将来のこずはわかりたせんが、すくなくずも珟時点においお、Reactアプリ開発の珟堎では、Reduxずいう状態管理のためのラむブラリが䜵甚されるこずが倚いず思いたす。

詊しにLesson 7のコヌドをRedux化しおみたす。Reduxを䜿うためには远加パッケヌゞが2぀必芁です。

npm install --save redux react-redux

Reduxが入るず、抂念的にもコヌド的にも䞀気に耇雑になりたす。
これ自䜓が非垞に奥深いテヌマなので、ここでは詳现な説明はしたせん。

Redux導入のメリットずしお感じおいるこずを列挙するず:

  • アプリ状態倉曎がActionずいう抂念でたずめられるので、芋通しが良くなる
  • propsのバケツリレヌが避けられる(Reduxがバケツリレヌを避ける唯䞀の手段ずいう意味ではないです)
  • PureComponentず䌌たパフォヌマンス最適化が自動的に埗られる
  • 匷力なデバッグツヌルが付いおくる

ずいった感じです。
Reduxを導入するず、䞋図のように状態の眮き堎所ず流れが倉わりたす。

react-redux.png

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider, connect } from 'react-redux'

// アクションを定矩する
const CHANGE_NAME = 'CHANGE_NAME'
const CHANGE_ADDRESS = 'CHANGE_ADDRESS'

// アクションはJavaScriptオブゞェクトで衚珟される。
// アクションを生成するためのAction Creatorず呌ばれる関数を定矩する。
function createChangeName(name) {
  return {
    type: CHANGE_NAME,
    payload: {
      name,
    },
  }
}

function createChangeAddress(address) {
  return {
    type: CHANGE_ADDRESS,
    payload: {
      address,
    },
  }
}

// アプリの初期状態
const initialState = {
  name: '',
  address: '',
}

// アプリの状態倉曎は、Reducerず呌ばれる「玔粋関数」で定矩される。
// 玔粋関数なので匕数を倉曎しおはいけない。
function reducer(state = initialState, action) {
  switch (action.type) {
    case CHANGE_NAME:
      return {
        ...state,
        name: action.payload.name,
      }
    case CHANGE_ADDRESS:
      return {
        ...state,
        address: action.payload.address,
      }
    default:
      return state
  }
}

// PersonForm,PersonInfoコンポヌネントはLesson 7で定矩したものずたったく同じ。
function PersonForm({ onNameChange, onAddressChange }) {
  return (
    <form>
      <label>
        指名: <input type="text" onChange={onNameChange} />
      </label>
      <label>
        䜏所: <input type="text" onChange={onAddressChange} />
      </label>
    </form>
  )
}

function PersonInfo({ name, address }) {
  const tableStyle = {
    borderCollapse: 'collapse',
  }
  const cellStyle = {
    border: 'solid black 1px',
    height: '1rem',
    padding: '0.3rem',
  }
  return (
    <table style={tableStyle}>
      <thead>
        <tr>
          <th style={cellStyle}>氏名</th>
          <th style={cellStyle}>䜏所</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td style={cellStyle}>{name}</td>
          <td style={cellStyle}>{address}</td>
        </tr>
      </tbody>
    </table>
  )
}

// コンポヌネントを、アプリのグロヌバルな状態が保持されるStoreず接続する。
// mapStateToPropsは、Storeから、コンポヌネントに枡すpropsを抜き出す関数
function mapStateToProps(state) {
  return {
    name: state.name,
    address: state.address,
  }
}
const PersonInfoConnected = connect(mapStateToProps, null)(PersonInfo)

function mapDispatchToProps(dispatch) {
  return {
    onNameChange: event => dispatch(createChangeName(event.target.value)),
    onAddressChange: event => dispatch(createChangeAddress(event.target.value)),
  }
}
const PersonFormConnected = connect(null, mapDispatchToProps)(PersonForm)

// Appコンポヌネントは、自身で`state`を持たなくなったのでスッキリした。
function App() {
  return (
    <div>
      <PersonFormConnected />
      <hr />
      <PersonInfoConnected />
    </div>
  )
}

// Storeむンスタンスを生成しお、Appコンポヌネントの倖偎に配眮する。
// これで、内偎のツリヌのどこからでも、Storeを参照できるようになる。
const store = createStore(reducer)

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('app')
)

実行結果

holding-state.png

参考


  1. ちなみに、蚭定䞍芁でReactを動かせる環境は、create-react-app, parcel, codesandboxなど、poi以倖にもいろいろなものがありたす。 ↩

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
23