Ant Design は、エレガントなユーザーインターフェイスを構築するのに役立つ多数の使いやすいコンポーネントを備えたReactUIライブラリです。

中国のコングロマリットAlibabaによって作成されたAntDesignは、Alibaba(もちろん)、Tencent、Baiduなどのいくつかの有名企業で使用されています。 Material-UIはGithubで4万個以上の星を獲得した最も人気のあるReactUIライブラリですが、 Ant Design は現在すぐ近くにあり、すぐにギャップを埋めています。

Ant Designのモバイル版もあり、ここで詳細を学ぶことができます

入門

このチュートリアルでは、AntDesignのコンポーネントのいくつかを紹介するための基本的なtodoアプリケーションを作成します。 最初のステップは、ボイラープレートをセットアップすることです。 create-react-appを使用してこれを行いました。

次に、antd依存関係をプロジェクトに追加する必要があります。

$ yarn add antd

# or, using npm:
$ npm install antd --save

<Todo />コンポーネントの構築を開始する前に、ルートコンポーネントにそのコンポーネントへの参照を追加します。

index.js
import React from "react";
import ReactDOM from "react-dom";
import Todo from "./todo";

import "./styles.css";

function App() {
  return (
    <div className="App">
      <Todo />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Todoコンポーネントの構築

これで、<Todo />コンポーネントの構築を開始できます。 次の内容のtodo.jsという名前の新しいファイルを開きます。

todo.js
import React from "react";

export default class Todo extends React.Component {
  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>
      </div>
    );
  }
}

.todoContainerがページの中央にうまく配置されるようにスタイルシートを編集します。

styles.css
.App {
  font-family: sans-serif;
  text-align: center;
}

.todoContainer {
  width: 75%;
  margin-left: auto;
  margin-right: auto;
}

涼しい! 次に、<Todo />コンポーネントに入力を追加しましょう。 antdで提供されているものを使用し、ライブラリのCSSファイルもインポートするようにします。

todo.js
import React from "react";
import { Input } from "antd";

// Don't forget to include the CSS styles for antd!
import "antd/dist/antd.css";

export default class Todo extends React.Component {
  render() {
    return (
      <div className="todoContainer" />
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
        />
      </div>
    );
  }
}

これで、テキスト入力ボックスをレンダリングしています。 ただし、何もしません。 ToDoのリストをレンダリングできるように、コンポーネントの状態にコンテンツを追加するための入力が必要です。 <Input />onPressEnterプロップを使用して、ユーザーが新しいToDoを送信したことを検出します。

todo.js
// --- snip ---

export default class Todo extends React.Component {
  constructor() {
    super();

    // Initialize the state
    this.state = {
      todos: []
    };
  }

  handlePressEnter = e => {
    // Create a todo object containing its index and content
    const todo = {
      index: this.state.todos.length,
      content: e.target.value
    };

    // Add the todo to our array
    const newTodos = this.state.todos.concat(todo);

    this.setState({
      todos: newTodos
    });

    // Clear input
    e.target.value = "";
  };

  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
          onPressEnter={this.handlePressEnter}
        />
      </div>
    );
  }
}

これで、handlePressEnter()は、ユーザーが新しいToDoアイテムを入力するたびにコンポーネントの状態を更新しますが、それでもレンダリングする必要があります。

この目的のために、AntDesignの<List />コンポーネントを使用できます。 dataSourceプロップとして配列を受け取り、renderItemプロップに渡される関数に従って配列をレンダリングします。

todo.js
import React from "react";
import { Input, List } from "antd";

import "antd/dist/antd.css";

export default class Todo extends React.Component {
  // --- snip ---

  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
          onPressEnter={this.handlePressEnter}
        />

        <List
          {/* emptyText sets the text to display in an empty list */}
          locale={{ emptyText: "No todo items" }}
          dataSource={this.state.todos}
          renderItem={item => (
            <List.Item>{item.content}</List.Item>
          )}
        />
      </div>
    );
  }
}

タダ! これで、基本的なtodoアプリが機能するようになりました。 ただし、それを改善するためにできることはまだまだあります。

ファンシーになる

ToDoアプリケーションが稼働しています。 ただし、追加する必要があるものは他にもあります。最も重要なのは、削除ボタンです。 日付ピッカーも追加します。なぜですか?

<Todo />が過度に複雑になるのを避けるために、<List.Item />を独自の個別のコンポーネントに抽出します。 また、新しいメソッドremoveTodo()を定義して、インデックスが指定されたToDoアイテムを削除します。 次に、そのメソッドを新しいコンポーネントに渡します。

削除ボタンとして機能するために、Antの<Icon />コンポーネントを使用できます。 これを<List.Item />‘のactionプロップに追加します。このプロップはコンポーネントの配列を取ります。 アイコンの完全なリストを表示するには、AntDesignWebサイトこのページを参照してください。

todo.js
import React from "react";
import { Input, List, Icon } from "antd";

import "antd/dist/antd.css";

export default class Todo extends React.Component {
  // --- snip ---

  removeTodo = index => {
    let newTodos = [...this.state.todos];

    // Remove element
    newTodos.splice(index, 1);

    // Decrement greater indexes
    for (let i = index; i < newTodos.length; i++) {
      newTodos[i].index -= 1;
    }

    // Update state
    this.setState({
      todos: newTodos
    });
  };

  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
          onPressEnter={this.handlePressEnter}
        />

        <List
          locale={{ emptyText: "No todo items" }}
          dataSource={this.state.todos}
          renderItem={item => (
            <TodoItem
              todo={item}
              removeTodo={this.removeTodo}
            />
          )}
        />
      </div>
    );
  }
}

class TodoItem extends React.Component {
  remove = () => {
    // Remove this TodoItem
    this.props.removeTodo(this.props.todo.index);
  };

  render() {
    return (
      <List.Item
        actions={[
          <Icon
            type="close-circle"
            theme="filled"
            onClick={this.remove}
          />
        ]}
      >
        {this.props.todo.content}
      </List.Item>
    );
  }
}

素晴らしい! あとは、Antの<DatePicker />コンポーネントを追加するだけです。 そのために、handlePressEnter()メソッドを更新してdateおよびdateStringプロパティを状態に保存しているtodoオブジェクトに追加します。 次に、これらのプロパティを更新するための追加のメソッドsetDate()が必要になります。

todo.js
import React from "react";
import { Input, List, Icon, DatePicker } from "antd";

import "antd/dist/antd.css";

export default class Todo extends React.Component {
  // --- snip ---

  handlePressEnter = e => {
    // Create a todo object containing its index, content,
    // as well as an empty date
    const todo = {
      index: this.state.todos.length,
      content: e.target.value,
      date: null,
      dateString: ""
    };

    // Add the new todo to our array
    const newTodos = this.state.todos.concat(todo);

    this.setState({
      todos: newTodos
    });

    // Clear input
    e.target.value = "";
  };

  setDate = (index, date, dateString) => {
    // Set the date of the given todo
    let newTodos = [...this.state.todos];
    newTodos[index].date = date;
    newTodos[index].dateString = dateString;

    // Initialize the state
    this.setState({
      todos: newTodos
    });
  };

  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
          onPressEnter={this.handlePressEnter}
        />

        <List
          locale={{ emptyText: "No todo items" }}
          dataSource={this.state.todos}
          renderItem={item => (
            <TodoItem
              todo={item}
              removeTodo={this.removeTodo}
              setDate={this.setDate}
            />
          )}
        />
      </div>
    );
  }
}

class TodoItem extends React.Component {
  remove = () => {
    // Remove this TodoItem
    this.props.removeTodo(this.props.todo.index);
  };

  handleDateChange = (date, dateString) => {
    // Update the date when changed
    this.props.setDate(this.props.todo.index, date, dateString);
  }

  render() {
    return (
      <List.Item
        actions={[
          <DatePicker
            format="MM/DD/YYYY"
            onChange={this.handleDateChange}
            value={this.props.todo.date}
          />,
          <Icon
            type="close-circle"
            theme="filled"
            onClick={this.remove}
          />
        ]}
      >
        {this.props.todo.content}
      </List.Item>
    );
  }
}

そして、voilà! 🎉

これで、AntDesignを利用した完全に機能するtodoアプリができました。 Antについて詳しく知りたい場合は、ドキュメントをご覧ください。

この投稿の完全なコードはCodeSandboxにあります。