Reactでプロフィールページ作りました

Reactを使ってプロフィールページを作ってみました。

完成品はここ

ソースはhttps://github.com/itamaev2/react-profileにあります。

使ったもの

  • create-react-app
  • material-ui

create-react-app

@chibicodeさんの記事を参考にしました。初めはreact-tutorialをベースに書いていたのですが、ES6化するのがメンドイ。。。

create-react-app使えば webpack,babel,ESLint等一発で設定させるので楽でした。

material-ui

http://www.material-ui.com/

見た目をいい感じにするために使いました。

、、、が結局いい感じにならなかった(╹◡╹)

振り返り

material-uiに時間を掛け過ぎた。

本来の目的はReactの知識を身につけることだったのですが、結果的に全体の9割の時間をmaterial-uiにかけていた。 もっと目的を意識して目的にそぐわない物は容赦なく切り捨てれば良かった。

ハマったこと

色々ハマることはありましたがその中でも一番時間をさかれたものを紹介します。

※ただの凡ミスです。

ある時画面が描画されなくなってコンソールに以下が際限なく出力され続けることがありました。

Warning: setState(...): Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

原因

renderの中でsetStateを呼んでいたこと

App.js

  : 
  handleOnContentsChange(stat) {
    this.setState({content: stat});
  }

  render() {
    return (
      <MuiThemeProvider>
        <div className="App">
          <Header onContentsChange={this.handleOnContentsChange} />
          <Contents content={this.state.content} />
        </div>
      </MuiThemeProvider>
    );
  }

Header.js

  :
render() {
  return (
    <div className="header">
      <FlatButton 
         label="About me"
         onClick={this.props.onContentsChange(ContentStat.AboutMe)} />// ★ここが悪い
      <FlatButton 
         label="Contact"
         onClick={this.props.onContentsChange(ContentStat.Contact)} />// ★ここが悪い
    </div>
  );
}

上記onClickのところでAppのonContentsChangeを渡したつもりになっていたが、 この記述だとここで実行されてしまいます。。

render時にstateが更新される=>stateが更新されるとrenderが実行される=>render時にstateが更新される=>stateが・・・・ということになり無限にrenderが実行されてしまっていた。

対処方法

以下のように修正して問題解決

Header.js(修正後)

  :
render() {
  return (
    <div className="header">
      <FlatButton
        label="About me"
        onClick={ () => this.props.onContentsChange(ContentStat.AboutMe) } />
      <FlatButton
        label="Contact"
        onClick={ () => this.props.onContentsChange(ContentStat.Contact) } />
    </div>
  );
}

皆さんもお気を付けくださいね。