ToDo

はじめてのReact #22「ToDoアプリを作る」 後編

3回に渡ってお送りしたToDoアプリ開発も最終回。今回はAjaxを利用しデータをサーバに保存してみます。

Propsのデータ型をチェック

以前取り上げたPropsのデータ型のチェックを導入しておきます。

プロジェクトも運用段階に入りComponentがどこからどのように呼び出されるか、収集がつかなくなったとしても呼び出し方さえ守ってもらえれば何とかなったりするものです(それが良いかはさて置き)。また誤った利用方法をするとテスト段階でエラーを明示的に出してくれるのもありがたいものです。

src/header.js

import PropTypes from 'prop-types';

// <Header>
//   React ToDo
// </Header>
Header.propTypes = {
  children: PropTypes.string.isRequired
};

src/todocreate.js

import PropTypes from 'prop-types';

// <ToDoCreate onClick={this.handleClick} />
ToDoCreate.propTypes = {
  onClick: PropTypes.func.isRequired
};

src/todolist.js

import PropTypes from 'prop-types';

// <ToDoList data={this.state.todo} remove={this.handleRemove}/>
ToDoList.propTypes = {
  data: PropTypes.array.isRequired,
  remove: PropTypes.func.isRequired
};

src/todoitem.js

import PropTypes from 'prop-types';

// <ToDoItem key={i.id} item={i} remove={this.props.remove} />
ToDoItem.propTypes ={
  item: PropTypes.object.isRequired,
  remove: PropTypes.func.isRequired
};

データをサーバ側で管理する

APIサーバを用意

Reactから話がずれますが、学習用に保存や取り出しを行うAPIサーバをNode.jsで準備します。かなり簡易的な物なので本番投入はしないでください。しないとは思いますがw

まずは適当な名前のディレクトリを作成しカレントディレクトリを別の場所に移します。今のプロジェクトは全く別の場所に作成してください。その後簡単にHTTPサーバを作成できるexpressを入れます。

$ mkdir apiserve; cd apiserve
$ npm install express

詳細は説明しませんが、以下のスクリプトをexpressをインストールしたディレクトリに適当な名前で保存します。ここではserve.jsとしました。

続きを読む

はじめてのReact #21「ToDoアプリを作る」 中編

前回に引き続き今回もToDoアプリを作っていきます。目標としてはフォームの使い勝手を向上させつつToDoの削除に対応するところまでとなります。

フォームを改良する

Submitイベントに対応

現状、登録フォームのテキストボックスに内容を入力しエンターキーを押した瞬間、再読込されてしまいます。これを防ぐには、formタグにonSubmitイベントを定義してあげればOK。今回はエンターキーを押すと確認用のダイアログを表示し、OKボタンが押されれば追加処理を行う形に変更しました。

src/todocreate.jsを以下のように変更します。

import React, { Component } from 'react';

class ToDoCreate extends Component {
  constructor(props){
    super(props);
    this.state = {
      newtodo: ""
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(e){
    this.setState({
      newtodo: e.target.value
    });
  }

  handleSubmit(e){
    let newtodo = this.state.newtodo;
    if(newtodo !== "" && window.confirm('本当に登録しますか?')){
      this.props.onClick(newtodo);
      this.setState({newtodo:""});
    }
    e.preventDefault();
  }

  render(){
    return(
      <form onSubmit={this.handleSubmit}>
        <input type="text" value={this.state.newtodo} onChange={this.handleChange}/>
        <button>追加</button>
      </form>
    );
  }
}

export default ToDoCreate;

注意すべき点としてはconfirm()ではなく、window.confirm()とする必要があるところでしょうか。

Validationを行う

もう一つの問題点として、テキストボックスが空でも登録されている点ですね。これも直して置きます。src/todocreate.jsのhandleSubmit()を以下のように変更しました。空文字列または2文字未満であれば何もしません。

  handleSubmit(e){
    e.preventDefault();

    let newtodo = this.state.newtodo;
    if(newtodo === "" || newtodo.length < 2){
      return(false);
    }

    if(newtodo !== "" && window.confirm('本当に登録しますか?')){
      this.props.onClick(newtodo);
      this.setState({newtodo:""});
    }
  }

テキストボックスにfocusする

ToDoを入力する際にわざわざテキストボックスをクリックするのも面倒なので、ページが読み込まれたと同時にfocusをしてあげます。src/todocreate.jsを以下のように変更します。

import ReactDOM from 'react-dom';  //追加

class ToDoCreate extends Component {
  // (snip)

  componentDidMount(){
    ReactDOM.findDOMNode(this.refs.newtodo).focus();
  }

  // (snip)

  render(){
    return(
      <form onSubmit={this.handleSubmit}>
        <input type="text" ref="newtodo" value={this.state.newtodo} onChange={this.handleChange}/>
        <button>追加</button>
      </form>
    );
  }
}

上記は変更した部分だけを抜き出しています。

まずReactDOMの機能を利用しますので新たにimportしました。
componentDidMount()はLifeCycleの機能。ComponentがDOMツリーに追加された瞬間に呼び出されます。ここで単純にfocus()メソッドを実行してあげればよいのですが、問題はどうやってテキストボックスを特定するかです。

今回はテキストボックスに<input type="text" ref="newtodo">といった形でref属性を追加しました。この属性をつけておくとReactから簡単に参照することができるようになります。この場合だとthis.ref.newtodoですね。

ReactDOM.findDOMNode()は最終的にDOMオブジェクトを返却しますので、これでテキストボックスを検索し、戻り値のDOMオブジェクトに対してfocus()を実行しているといます。

Lifecycleについては過去の記事を参照してください。

続きを読む

はじめてのReact #20「ToDoアプリを作る」 前編

前回準備した環境を使って、早速Webアプリを作ってみたいと思います。こういうときはToDoアプリを作るのが伝統となっていますので、それに習いますw

なお、本来であればテストコードを書きながら進めるべきだとは思いますが、今回は割愛しております。

準備編

プロジェクトの作成

rtodoという名前でプロジェクトを新規作成しました。rはReactで作るぞという意思表示で特に意味はありませんw 好きな名称をつけてください。

$ create-react-app rtodo

Gitリポジトリの準備

GitHubにもrtodoという名前でリポジトリを準備しました。まずはこいつにgit pushします。
https://github.com/katsube/rtodo

$ git remote add origin git@github.com:katsube/rtodo.git
$ git push -u origin master

Componentを作ってみる

新しいComponentを作る

まずは腕鳴らしに簡単なComponentを用意してみます。src/header.jsというファイルを作成し、その中に以下のコードを記述します。render()でタグを描画しているだけですね。h1の中はprops.childrenでもらった文字列をそのまま出しています。

import React, { Component } from 'react';

class Header extends Component {
  render() {
    return(
      <header>
        <h1>{this.props.children}</h1>
      </header>
    );
  }
}

export default Header;

最後のexport文を忘れないように気をつけてください。これを記述することで他のファイルからこのComponentを利用することができるようになります。

子供の要素にアクセスする方法(this.props.children)については過去の記事を参照してください。

続きを読む