28
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScript初心者がReact+Reduxでブログのフロントエンドを作成するまで

Last updated at Posted at 2017-11-04

はじめに

JavaScriptの基礎知識がだいたいわかったので、スキマ時間(4時間くらい)で簡単なブログのフロントエンドをReact+Reduxで構築した。
といっても、Modern React with Reduxというコースのセクション9を見ながら手を動かしただけ。JavaScript初心者だが、セクション9から見始めても特に問題なかった。

ソースコード

実装時のメモも含めて、以下に保存してある。
github.com/tomoyamachi/react-blog-sample

できるようになったこと

  • SPAだが、URLごとで表示するDOMを分ける
  • 非同期でAPI通信を行う
  • 非同期処理が完了してから、表示処理を実行する
  • 送信フォームの管理(バリデーション含む)
  • ESの言語仕様がざっくりわかる
  • 一人である程度のプロジェクトをつくる

今後

実践でそのまま利用できそうなことが詰まっていた。作成後1時間くらいはできたコードをいじって、各コードの役割を理解した。
次は、テストやコード品質の担保をしたいので、Advanced React and Reduxを見ようと思っている。

もし、React+Reduxを利用した中規模以上プロジェクトのソースコードが公開されてれば、かなりレベル上げができそう。
軽く探しているが見当たらないので、もしあれば知りたい。

以下、パッケージなどのメモ

SPAだが、URLごとで表示内容を出し分けたい

react-router-dom を利用。Switchを使わない場合、パスの正規表現に引っかかったものすべてのコンポーネントが表示される。

なお、parameterを取得したいときは、Componentの this.props.match.params.{name}の形で取得できる。

index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import reducers from './reducers';
import promise from 'redux-promise';
import PostsIndex from './components/posts_index';
import PostsNew from './components/posts_new';
import PostsShow from './components/posts_show';
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <BrowserRouter>
      <div>
        <Switch>
          <Route path="/posts/new" component={PostsNew} />
          <Route path="/posts/:id" component={PostsShow} />
          <Route path="/" component={PostsIndex} />
        </Switch>
      </div>
    </BrowserRouter>
  </Provider>
  , document.querySelector('.container'));

API通信がしたい

axiosを利用。
レスポンスが返ってきてからの処理を入れる場合は、axios.{HTTPmethod}().then() でつなげる。エラー時の挙動は.catch()で管理

actions/index.js
export function createPost(values, callback) {
    const request = axios.post(`${ROOT_URL}/posts${API_KEY}`, values)
          .then(() => callback())
          .catch((e) => console.log(e));
    return {
        type: CREATE_POSTS,
        payload: request
    };
}

非同期処理を管理したい

redux-promiseを利用する。ミドルウェアに入れるだけで、利用できるようになる。非同期処理が完了してから、処理を行えるようになる。 ※細かなことは分かってない

const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
...(略)

フォームの管理がしたい

redux-form を利用。
バリデーションはreduxFormの引数にvalidate を指定すればいい。
フォーム操作後にエラーを表示したい場合は、meta.touchedで判定。

import React, {Component} from 'react';
import {Field, reduxForm} from 'redux-form';
import { connect } from 'react-redux';
import { Field, reduxForm } from 'redux-form';

class PostsNew extends Component {
    renderField(field) {
        const {meta: { touched, error }} = field;
        const className = `form-group ${touched && error ? 'has-danger' : ''}`;

        return (
            <div className={className}>
              <label>{field.label}</label>
              <input
                className="form-control"
                type="text"
                {...field.input}
                />
              <div className="text-help">
                {field.meta.touched ? field.meta.error : ''}
              </div>
            </div>
        );
    }

    onSubmit(values) {
        this.props.createPost(values, () => {
            this.props.history.push('/');
        });
    }

    render() {
        const { handleSubmit } = this.props;
        return (
            <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
              <Field
                label="Title"
                name="title"
                component={this.renderField}
                />
              <button type="submit" className="btn btn-primary">Submit</button>
            </form>
        );
    }
}

function validate(values) {
    const errors = {};
    if(!values.title) {
        errors.title = "enter a title!";
    }
    return errors;
}

export default reduxForm({
    validate,
    form: 'PostsNewForm'
})(
    connect(null,{ createPost })(PostsNew)
);
28
28
0

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
  3. You can use dark theme
What you can do with signing up
28
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?