20190502のReactに関する記事は6件です。

【最新サービス試用⑥】簡単にドキュメントやポートフォリオを作成できるサイト作成ツールの「Docusaurusu」を試用

  • 日々輩出される素晴らしき最新サービスを素早く試して、不鮮明な先見性を堂々と誇示する記事第六弾。
  • 幾度となく、「最先端」「自動生成」というサービスに一目散に飛びついてきた生活は、元号変化の新時代も継続。
  • 今回は、マークダウン形式で簡単にドキュメントやブログを作成できるジェネレータの「Docusaurus」を試用することにしよう。

目的とゴール

  • Docusaurusの概要や特徴の把握
  • 類似サービスの把握
  • Docusaurusの導入方法の把握
  • プロジェクトの作成方法の把握
  • サーバーの起動方法の把握
  • 新規ページの作成方法の把握
  • 様々なマークダウン形式の表示確認
  • ※今回はデプロイやCIツールとの連携は行わない

概要

  • Docusaurusは、Facebook開発のドキュメント作成ジェネレーター。
  • マークダウンを用いて、簡単にドキュメントを作成できるため、主にオープンソースプロジェクトのドキュメント生成用として使われている。
  • 公開やCIツールとの連携が容易であるため、ポートフォリオサイト作成としても使われている。
  • 公式サイト

特徴

マークダウン形式でのドキュメント記述

  • ドキュメントやコンテンツをマークダウンで記述することができ、自動でページやHTMLファイルを出力してくれる。
  • シンタックスハイライトやテーブル等、様々なマークダウン形式に対応している。

Reactを用いた記述

  • レイアウトの拡張やカスタマイズを、Reactで記述することができる。

翻訳機能対応

  • Crowdinという翻訳サービスとの連携で、簡単にドキュメントの多言語対応が実装できる。

検索機能対応

  • DocSearchという検索サービスとの連携で、簡単にドキュメントの文章検索機能を実装できる。

バージョニング

  • ドキュメントが古くなっても、最新の内容に基づいて、最適なバージョン管理を行うことができる。

サイト公開とCI連携の容易さ

  • ホスティングサービスであるNetlifyGitHub Pagesを利用して、簡単にサイトを公開することができる。
  • また、CircleCITravisCI等の、CIツールとの連携にも対応

類似サービス

手順

環境

  • Mac OS X 10.13.4Mac OS X 10.13.4
  • NodeJs v11.6.0

導入

  • ターミナル(コマンドプロンプト)を開き、下記のコマンドをうち、Docusaurusを導入する。
    • Nodejsが入っていない場合、インストールする。
$ npm install --global docusaurus-init

プロジェクト作成

  • 下記のコマンドをうち、Docusaurus新規プロジェクトを作成する。
# プロジェクトフォルダの作成
$ mkdir ~/docsaurus_sample
# プロジェクトフォルダへ移動
$ cd ~/docsaurus_sample
# Docusaurus新規プロジェクトの作成
$ docusaurus-init

構成

  • docusaurus-initコマンドで作成されたプロジェクトは、下記のような構成になっている。
root
├── docs
│   ├── doc1.md
│   ├── doc2.md
│   ├── doc3.md
│   ├── exampledoc4.md
│   └── exampledoc5.md
└── website
    ├── blog
    │   ├── 2016-03-11-blog-post.md
    │   ├── 2017-04-10-blog-post-two.md
    │   ├── 2017-09-25-testing-rss.md
    │   ├── 2017-09-26-adding-rss.md
    │   └── 2017-10-24-new-version-1.0.0.md
    ├── core
    │   └── Footer.js
    ├── package.json
    ├── pages
    ├── sidebars.json
    ├── siteConfig.js
    └── static
  • 主に下記の内容で、適切なファイルを配置していく
    • docs/・・・ドキュメントのMarkdownファイルを配置していく。
    • website/blog・・・ブログ用記事の配置していく。
    • website/pages・・・通常ページファイルを配置していく。
    • website/static・・・サイトの画像やスタイルを配置していく。

チュートリアルページ確認

  • 下記のコマンドをうち、ローカルサーバーを起動する。
# websiteフォルダへ移動
$ cd ~/docsaurus_sample/website
# ローカルサーバー起動
$ npm start

image

新規ページ作成

1. ドキュメントページ作成

  • docs/配下に、.md形式でファイルを新規作成して、配置する。
    • 今回は、サンプルとして、intro.mdとして作成する。
  • intro.mdの中身を下記にする。
    • シンタックスハイライト部分の「\」は不要。
intro.md
---
id: intro
title: t_o_d on intro
---

# タイトルテスト

## サブタイトルテスト

### 本文テスト

- 本文テスト

### ネストテスト

- 本文テスト
    - ネストテスト

### 書式等テスト

- **太字テスト**
- ~~打消し線テスト~~
- <details><summary>折りたたみテスト</summary>折りたたまれているようだ</details>
- > 引用テスト

### 水平線テスト

- 水平線テスト
---

### 画像テスト

![penguin](https://user-images.githubusercontent.com/44114228/57018373-3eedac80-6c5e-11e9-91e8-2d5ce7d418ac.png)

### シンタックスハイライトテスト

\```ruby
# テスト
puts "Hello t_o_d"
\```

### テーブルテスト

|タイトル|内容|
|:---:|:---:|
|イントロ|テスト|

### リンクテスト

- [リンク](https://www.google.co.jp/)
  • 中身を記述後、website\sidebars.jsonに作成したファイルを、下記のように追加する。
sidebar.json
{
  "docs": {
    "Docusaurus": ["doc1"],
    "First Category": ["doc2"],
    "Second Category": ["doc3"],
    "Intro": ["intro"]
  },
  "docs-other": {
    "First Category": ["doc4", "doc5"]
  }
}
  • 中身を記述後、http://localhost:3000/docs/intro にアクセスして、下記の画面が表示されることを確認する。
    • アクセスできない場合、ローカルサーバーをCtrl + Cで終了して、再度npm startで起動する。

image.png
image.png

2. 通常ページ作成

  • website\pages\en\配下に、.js形式でファイルを新規作成して、配置する。
    • 今回は、サンプルとして、test.jsとして作成する。
  • test.jsの中身を、既存のindex.jsを少し変えて、下記のようにする。
    • .jsの中身はReact記法で書くことができる。
test.js
const React = require('react');

const CompLibrary = require('../../core/CompLibrary.js');

const Container = CompLibrary.Container;

function Test(props) {
    return (
        <div className="docMainWrapper wrapper">
            <Container className="mainContainer documentContainer postContainer">
                <h1>Hello t_o_d</h1>
                <p>I am t_o_d</p>
            </Container>
        </div>
    );
}

module.exports = Test;
  • 記述して保存後、http://localhost:3000/test にアクセスして、下記の画面が表示されることを確認する。

image.png

まとめ

  • 今回は、サイト生成ジェネレーターの試用ということで、日々増殖を続ける自動生成ツールの恩恵を際限なくいただきながら、記事を書く。
  • 「OSSプロジェクトのドキュメント用だが、技術記事やポートフォリオとしても利用できそう」という、主目的の「OSS」の高権威専用用語から、全力で逃避を図ろうとする。
  • 「試用ということで使ってみたが、検索機能や翻訳機能、CI連携等も確かめてみよう」という、今後の目標を確定した直後に、次なる豊かな最新サービスを探す迷走生活。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【最新サービス試用⑥】簡単にドキュメントやポートフォリオを作成できるサイト作成ツールの「Docusaurus」を試用

  • 日々輩出される素晴らしき最新サービスを素早く試して、不鮮明な先見性を堂々と誇示する記事第六弾。
  • 幾度となく、「最先端」「自動生成」というサービスに一目散に飛びついてきた生活は、元号変化の新時代も継続。
  • 今回は、マークダウン形式で簡単にドキュメントやブログを作成できるジェネレータの「Docusaurus」を試用することにしよう。

目的とゴール

  • Docusaurusの概要や特徴の把握
  • 類似サービスの把握
  • Docusaurusの導入方法の把握
  • プロジェクトの作成方法の把握
  • サーバーの起動方法の把握
  • 新規ページの作成方法の把握
  • 様々なマークダウン形式の表示確認
  • ※今回はデプロイやCIツールとの連携は行わない

概要

  • Docusaurusは、Facebook開発のドキュメント作成ジェネレーター。
  • マークダウンを用いて、簡単にドキュメントを作成できるため、主にオープンソースプロジェクトのドキュメント生成用として使われている。
  • 公開やCIツールとの連携が容易であるため、ポートフォリオサイト作成としても使われている。
  • 公式サイト

特徴

マークダウン形式でのドキュメント記述

  • ドキュメントやコンテンツをマークダウンで記述することができ、自動でページやHTMLファイルを出力してくれる。
  • シンタックスハイライトやテーブル等、様々なマークダウン形式に対応している。

Reactを用いた記述

  • レイアウトの拡張やカスタマイズを、Reactで記述することができる。

翻訳機能対応

  • Crowdinという翻訳サービスとの連携で、簡単にドキュメントの多言語対応が実装できる。

検索機能対応

  • DocSearchという検索サービスとの連携で、簡単にドキュメントの文章検索機能を実装できる。

バージョニング

  • ドキュメントが古くなっても、最新の内容に基づいて、最適なバージョン管理を行うことができる。

サイト公開とCI連携の容易さ

  • ホスティングサービスであるNetlifyGitHub Pagesを利用して、簡単にサイトを公開することができる。
  • また、CircleCITravisCI等の、CIツールとの連携にも対応

類似サービス

手順

環境

  • Mac OS X 10.13.4Mac OS X 10.13.4
  • NodeJs v11.6.0

導入

  • ターミナル(コマンドプロンプト)を開き、下記のコマンドをうち、Docusaurusを導入する。
    • Nodejsが入っていない場合、インストールする。
$ npm install --global docusaurus-init

プロジェクト作成

  • 下記のコマンドをうち、Docusaurus新規プロジェクトを作成する。
# プロジェクトフォルダの作成
$ mkdir ~/docsaurus_sample
# プロジェクトフォルダへ移動
$ cd ~/docsaurus_sample
# Docusaurus新規プロジェクトの作成
$ docusaurus-init

構成

  • docusaurus-initコマンドで作成されたプロジェクトは、下記のような構成になっている。
root
├── docs
│   ├── doc1.md
│   ├── doc2.md
│   ├── doc3.md
│   ├── exampledoc4.md
│   └── exampledoc5.md
└── website
    ├── blog
    │   ├── 2016-03-11-blog-post.md
    │   ├── 2017-04-10-blog-post-two.md
    │   ├── 2017-09-25-testing-rss.md
    │   ├── 2017-09-26-adding-rss.md
    │   └── 2017-10-24-new-version-1.0.0.md
    ├── core
    │   └── Footer.js
    ├── package.json
    ├── pages
    ├── sidebars.json
    ├── siteConfig.js
    └── static
  • 主に下記の内容で、適切なファイルを配置していく
    • docs/・・・ドキュメントのMarkdownファイルを配置していく。
    • website/blog・・・ブログ用記事の配置していく。
    • website/pages・・・通常ページファイルを配置していく。
    • website/static・・・サイトの画像やスタイルを配置していく。

チュートリアルページ確認

  • 下記のコマンドをうち、ローカルサーバーを起動する。
# websiteフォルダへ移動
$ cd ~/docsaurus_sample/website
# ローカルサーバー起動
$ npm start

image

新規ページ作成

1. ドキュメントページ作成

  • docs/配下に、.md形式でファイルを新規作成して、配置する。
    • 今回は、サンプルとして、intro.mdとして作成する。
  • intro.mdの中身を下記にする。
    • シンタックスハイライト部分の「\」は不要。
intro.md
---
id: intro
title: t_o_d on intro
---

# タイトルテスト

## サブタイトルテスト

### 本文テスト

- 本文テスト

### ネストテスト

- 本文テスト
    - ネストテスト

### 書式等テスト

- **太字テスト**
- ~~打消し線テスト~~
- <details><summary>折りたたみテスト</summary>折りたたまれているようだ</details>
- > 引用テスト

### 水平線テスト

- 水平線テスト
---

### 画像テスト

![penguin](https://user-images.githubusercontent.com/44114228/57018373-3eedac80-6c5e-11e9-91e8-2d5ce7d418ac.png)

### シンタックスハイライトテスト

\```ruby
# テスト
puts "Hello t_o_d"
\```

### テーブルテスト

|タイトル|内容|
|:---:|:---:|
|イントロ|テスト|

### リンクテスト

- [リンク](https://www.google.co.jp/)
  • 中身を記述後、website\sidebars.jsonに作成したファイルを、下記のように追加する。
sidebar.json
{
  "docs": {
    "Docusaurus": ["doc1"],
    "First Category": ["doc2"],
    "Second Category": ["doc3"],
    "Intro": ["intro"]
  },
  "docs-other": {
    "First Category": ["doc4", "doc5"]
  }
}
  • 中身を記述後、http://localhost:3000/docs/intro にアクセスして、下記の画面が表示されることを確認する。
    • アクセスできない場合、ローカルサーバーをCtrl + Cで終了して、再度npm startで起動する。

image.png
image.png

2. 通常ページ作成

  • website\pages\en\配下に、.js形式でファイルを新規作成して、配置する。
    • 今回は、サンプルとして、test.jsとして作成する。
  • test.jsの中身を、既存のindex.jsを少し変えて、下記のようにする。
    • .jsの中身はReact記法で書くことができる。
test.js
const React = require('react');

const CompLibrary = require('../../core/CompLibrary.js');

const Container = CompLibrary.Container;

function Test(props) {
    return (
        <div className="docMainWrapper wrapper">
            <Container className="mainContainer documentContainer postContainer">
                <h1>Hello t_o_d</h1>
                <p>I am t_o_d</p>
            </Container>
        </div>
    );
}

module.exports = Test;
  • 記述して保存後、http://localhost:3000/test にアクセスして、下記の画面が表示されることを確認する。

image.png

まとめ

  • 今回は、サイト生成ジェネレーターの試用ということで、日々増殖を続ける自動生成ツールの恩恵を際限なくいただきながら、記事を書く。
  • 「OSSプロジェクトのドキュメント用だが、技術記事やポートフォリオとしても利用できそう」という、主目的の「OSS」の高権威専用用語から、全力で逃避を図ろうとする。
  • 「試用ということで使ってみたが、検索機能や翻訳機能、CI連携等も確かめてみよう」という、今後の目標を確定した直後に、次なる豊かな最新サービスを探す迷走生活。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React 初心者まとめ②

Reactアプリケーションはelement(要素)という構成ブロックにより構成されています。
コンポーネントは要素によって構成されたものです。
コンポーネントを使うことにより、UIを部品に分割し分離させることができます。

コンポーネントはpropsと呼ばれる任意の値を受け取り、画面上に表示すべきものを返すReaxt要素を返します。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

これはpropsで受け取ったnameを表示させる関数コンポーネントです。

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

これは等価なコードです、classコンポーネントを使う際はextends React.Componentを記載して下さい。
またファイル冒頭にimport React, { Component } from 'react';を書くことも必要です。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

このコードではelementと定義された要素を引数としてReactDOM.renderが呼び出されます。
そのあとelementに代入されたwelcomeコンポーネントを呼び出し、その時propsとしてname=’Sara’が渡されます。
その後ReactDOMが

Hello, Sara

になるようDOMを更新します。

Reactでは

<welcome />はDOMタグ
<Welcome />はコンポーネント
と認識されることを覚えておきましょう。

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello World</h1>
      </div>
    );
  }
}

これはclassコンポーネントですが、特徴として内部にプライベート状態(state)をもたせたり、
生成状況によって呼び出されるライフサイクルメソッドを持っています。
主に親コンポーネントとして使用し関数コンポーネントで作った子コンポーネントに、保持している値を伝える親玉のような存在と言えるでしょう。

const App = (props) => {
  return (
    <div>
      <h1>Hello World</h1>
    </div>
    <h2>Hello React</h2>
  );
};

これは同レベルのReact Elementがあるためエラーになります。

const App = (props) => {
  return (
    <div>
      <h1>Hello World</h1>
      <h2>Hello React</h2>
    </div>
  );
};

とdivタグで囲ってあげましょう。

// 親コンポーネント
class Parent extends React.Component {
  //superは必須です
  constructor(props) {
    super(props);
    this.state = {
      value1: 'foo',
      value2: [ 'bar', 'baz' ],
    };
  }
  render() {
    return (
      <div>
        <Child1 data={this.state.value1} />
        <Child2 data={this.state.value2} />
      </div>
    );
  }
}

// Functionalコンポーネントで受け取る場合
const Child1 = (props) => (
  <div>
    {props.data}
  </div>
);

// Classコンポーネントで受け取る場合
class Child2 extends React.Component {
  render() {
    return (
      <div>
        {this.props.data}
      </div>
    );
  }
}

親で独自の名前を付けて子に流していく流れですね。
クラスコンポーネント間でも受け取ることができます。

viewで発生したイベントハンドラはクラスコンポーネントのメソッドで設定して下さい。
その際はキャメルケースで書く必要があります。
またコールバック関数として実行する際にthisが機能するようconstructor()内でthisをbindしておく必要があります。
これはjavascriptにまつわる話題です。

ReactDom.render(
  <App />,
  document.querySelector('.content')
);

これは冒頭紹介したコードです、深掘りしていきましょう。
親コンポーネント(App.js)のrender()メソッドで返されたレンダリングの実態は仮想DOMと呼ばれるものです。仮想DOMではブラウザで表示できないので生のDOMに変換する必要があるのですが、そこでこのコードが活躍します。
第一引数に親コンポーネント、第二引数にhtmlで表示・挿入する部分を渡しています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reactで入れ子のstateをsetStateするときにuncontrolledになる

表題の件、地味にハマったのでメモしておきます。

こんなWarningが出るやつです。

Warning: A component is changing a controlled input of type text
to be uncontrolled. Input elements should not switch from controlled
to uncontrolled (or vice versa). Decide between using a controlled or
uncontrolled input element for the lifetime of the component.
More info: https://fb.me/react-controlled-components
import React  from 'react';
import update from 'immutability-helper';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      text1: 'aaa',
      group: {
        text2: 'bbb',
        text3: 'ccc',
        text4: 'ddd',
      },
    }
  }

  handleText1 = (event) => {
    // [通常]これは入れ子でないので普通にsetStateしてOK
    this.setState({ text1: event.target.value });
  }

  handleText2 = (event) => {
   // [問題]これはWarningになる
    // (Warning: A component is changing a controlled input of type text to be uncontrolled.)
    // uncontrolledになるのは、フォームのvalueがnullやundefinedになる場合に発生する。
    // ここでは、this.state.group.text3やtext4がセットされずundefinedになるために警告がでる。
    this.setState({ 
      group: { text2: event.target.value }
    });
  }

  handleText3 = (event) => {
    // [解1]上記エラーを回避するためには、一度this.state.groupをコピーし、
    // コピーしたオブジェクトを更新後、それをsetStateする。
    const newGroupState = Object.assign({}, this.state.group);
    newGroupState.text3 = event.target.value;
    this.setState({ group: newGroupState });
  }

  handleText4 = (event) => {
    // [解2]immutability-helperを使う。
    // https://github.com/kolodny/immutability-helper
    this.setState({ group: update(this.state.group, { text4: {$set: event.target.value} }) });
  }


  render() {
    return (
      <React.Fragment>
        text2を変更するとコンソールにwarningが出る。
        <table>
          <tbody>
            <tr><td>text1</td><td><input type="text" value={this.state.text1}       onChange={this.handleText1.bind(this)} /></td></tr>
            <tr><td>text2</td><td><input type="text" value={this.state.group.text2} onChange={this.handleText2.bind(this)} /></td></tr>
            <tr><td>text3</td><td><input type="text" value={this.state.group.text3} onChange={this.handleText3.bind(this)} /></td></tr>
            <tr><td>text4</td><td><input type="text" value={this.state.group.text4} onChange={this.handleText4.bind(this)} /></td></tr>
            <tr><td>state</td><td>{JSON.stringify(this.state)}</td></tr>
          </tbody>
        </table>
      </React.Fragment>
    );
  }
}

export default App;

ソース:
https://github.com/xojan0120/uncontrolled_warning_test

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React + ReduxでTodoアプリを作ってみよう!『Add Todo編』

概要

前回までの記事では、ReactとReduxの基本をまとめさせて頂きました。今回からは、さらにもう一歩踏み込んでReactとReduxを用いたTodoアプリを作ってみたいと思います。(参考:Redux Basic Tutrial

前回の記事
『Redux』を用いて状態管理をしてみよう!

今回は、TodoをTodoListに追加する『Add Todo』の機能を実装したいと思います。

Action & Action Creator

まずは、ActionとAction Creatorの定義から始めていきましょう!
ActionのtypeはADD_TODOと定義し、textは入力されたTodo、idは追加されていくTodoの番号となります。

src/actions/index.js
export ADD_TODO = 'ADD_TODO';

let nextTodoId = 0;
export const addTodo = text => {
 return {
  type: ADD_TODO,
  id: nextTodoId++,
  text, //text: textを省略
 };
};

Reducer

次にReducerを定義していきましょう!
まずは全てのReducerを結合するファイルであるsrc/reducers/index.jsを作成しましょう!combineReducers()などに関して知りたい方は前回の記事をご覧ください

src/reducers/index.js
import {combineReducers} from 'redux';
import todos from './todo';

const todoApp = combineReducers({todos});

export default todoApp;

続いて、実際にActionから発行されるtypeを受け取って状態遷移を行うsrc/reducers/todo.jsを書いていきましょう!
...stateによって今まで追加されてきたTodoが、{id: action.id, text: action.text}によって新しく追加されたTodoが配列に格納され返ってきます。

src/reducers/todo.js
import {ADD_TODO} from '../actions';

const todos = (state = [], action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, {id: action.id, text: action.text}];
    default:
      return state;
  }
};

export default todos;

store

storeはアプリケーション内のstate(状態)を管理しているところです。詳しくは先ほどと同様に前回の記事を参照してください。

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

import App from './components/App';
import {addTodo} from './actions';
import * as serviceWorker from './serviceWorker';
import reducers from './reducers';

let store = createStore(reducers);

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

Presentational Components

『Presentational Components』はpropsとして受け取ったデータを表示することに専念するコンポーネントになります。

src/components/Todo.jsではpropsとして受け取ったデータを表示します。

src/components/Todo.js
import React from 'react';
import PropTypes from 'prop-types';

const Todo = ({text}) => {
  return <li>{text}</li>;
};

Todo.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Todo;

一方src/components/TodoList.jsでは、mapを用いてpropsとして受け取ったtodosをTodo Componentに渡しています。{...todo}はtodoの全ての要素を表しており、id={todo.id}text=todo.textと同じ意味を持っています。

src/components/TodoList.js
import React from 'react';
import propTypes from 'prop-types';
import Todo from './Todo';

const TodoList = ({todos}) => {
  return (
    <ul>
      {todos.map(todo => (
        <Todo key={todo.id} {...todo} />
      ))}
    </ul>
  );

  TodoList.propTypes = {
    todos: propTypes.arrayOF(
      propTypes.shape({
        id: propTypes.number.isRequired,
        text: propTypes.string.isRequired,
      }).isRequired
    ).isRequired,
  };
};

export default TodoList;

Container Components

Container componentはPresentational componentに具体的なデータやコールバック関数を与えるコンポーネントです。

src/containers/VisibleTodoList.jsでは、まずはmapStateToPoropsを用いてstateから必要な情報をpropsとしてマッピングさせます。そしてconnect関数を用いてTodoList Componentとstateを結びつけて、VisibleTodoListとしてexportします。

src/containers/VisibleTodoList.js
import {connect} from 'react-redux';
import TodoList from '../components/TodoList';

const mapStateToPorops = state => {
  return {todos: state.todos};
};

const VisibleTodoList = connect(mapStateToPorops)(TodoList);

export default VisibleTodoList;

これで、ブラウザにTodoを表示させることが出来るようになりましたが、まだTodoを入力するFormがないので作成していきます。

src/containers/AddTodo.js
import React from 'react';
import {connect} from 'react-redux';
import {addTodo} from '../actions';

let AddTodo = ({dispatch}) => {
  let input;

  return (
    <div>
      <input
        ref={node => {
          input = node;
        }}
      />
      <button
        onClick={() => {
          dispatch(addTodo(input.value));
          input.value = '';
        }}>
        Add Todo
      </button>
    </div>
  );
};

AddTodo = connect()(AddTodo);

export default AddTodo;

src/containers/AddTodo.jsではdispatch(addTodo(input.value));と書くことで、buttonを押した際にinput要素に入力された内容をTodoに追加出来るようになっています。

またinput要素内でrefを用いておりますが、refを用いることで、あらかじめ宣言していたinputに入力された内容を格納することができます。今回は以下に示す3つの方法の中でrefコールバック属性を用いる方法を選択しています。

Refsを扱うには3つ方法があります。

  • React.createRefメソッドを用いる(v16.3.0以上で利用可能)
  • refコールバック属性を用いる
  • ref文字列属性を用いる(非推奨 v17で削除)

参考:ReactのRefsを正しく取り扱う

ブラウザに表示させてみよう!

では、src/components/App.js<AddTodo /><VisibleTodoList />を追加してブラウザに表示させてみましょう!

src/components/App.js
import React from 'react';
import VisibleTodoList from '../containers/VisibleTodoList';
import AddTodo from '../containers/AddTodo';

const App = () => {
  return (
    <div className="App">
      <AddTodo />
      <VisibleTodoList />
    </div>
  );
};

export default App;

これで『Add Todo』の機能は実装できたと思います。次回は、Todoの完了・未完了を切り替える『Toggle Todo』の機能を実装していきましょう!

ezgif.com-optimize (1).gif

リファレンス

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React 初心者まとめ

Reactを自分なりにまとめてみた①

初めての投稿です。
PHPとLaravelを使ったアプリ作成の経験はあったのですが、Reactを学んで興味深い点などあったので自分用のメモとして残します。
Javascriptのコーディング経験もなく、ES6以前にJavascriptって何状態だったので同じような初学者の方へ参考にもなればと思います。

まず前提としてReactはJavascriptのライブラリなので、Javascriptの最低限の理解が必要というのは言うまでもないことなのですが、他の言語をやったことがある方でしたら、入りやすいのかなと感じました。

Javascriptを完璧にやってからReactをやるというのも良いと思いますが、ES6の記法をさらってReactを触り始めてもいいんじゃないかなって思います。

ここで重要なのは(僕自身意識してます)、分かんないのはJavascriptなのかReactなのかを明確にする必要があるということです。

最初ということでJSXについての記述がほとんどになりますのでご存知のかたは②にお進み下さい。

const element = <h1>Hello, world!</h1>;

この構文はJSXと呼ばれるJavascriptの拡張構文です。
ReactではこのJSXを多用します。

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
ReactDOM.render(
  element,
  document.getElementById('root')
);

constでnameを宣言して、中括弧に囲んでJSX内で使用しています。
PHPで言うところの
$name = “Josh Perez”;
のようなものですが、Javascriptにはlet,const,varが存在しているので差異は理解する必要があります。

const element = <div tabIndex="0"></div>;

文字列リテラルを属性として指定するために引用符を使用できます。
JSXではキャメルケースのプロパティ命名規則を使用します。
キャメルケースとは、アルファベットで複合語やフレーズを表記する際、各単語や要素語の先頭の文字を大文字で表記する手法のことです。
例えばtabindexはtabIndexとなります。

const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;

RectDOMはJSXに埋め込まれた値をレンダリングされる前にエスケープするので、
ユーザーの入力したあらゆるコードが注入できないことが保証されています。
PHPで言うところのhtmlspecialchars()のようなものが、JSXでは担保されているということでしょうか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む