LoginSignup
13
18

More than 5 years have passed since last update.

ReactでTrelloみたいなToDoリスト<1> props

Last updated at Posted at 2017-06-22

関連記事

作るもの

ToDoリストのイメージ

스크린샷 2017-06-20 10.46.31.png

Appの構成

스크린샷 2017-06-20 10.47.31.png

  • KanbanBoardコンポーネントはTo Do、In Progress、Doneという三つのListコンポーネントを持つ。
  • 各ListコンポーネントはCardコンポーネントを持つ。
  • CardコンポーネントはCheckListコンポーネントを持つ。

ToDoリスト(immutable)

propsの伝達を理解するために、親コンポーネントから子コンポーネント順で作成する。
画面に表示するための仮データを持っているcardsListを作る。
KanbanBoardコンポーネントにcardsListをpropsとして渡す。

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import KanbanBoard from './components/KanbanBoard';
import registerServiceWorker from './registerServiceWorker';
import './index.css';

const cardsList = [
  {
    id: 1,
    title: 'Read the Book',
    description: 'I should read the whole book',
    status: 'in-progress',
    tasks: [],
  },
  {
    id: 1,
    title: 'Write some code',
    description: 'Code along with the samples in the book',
    status: 'todo',
    tasks: [
      {
        id: 1,
        name: 'ContactList Example',
        done: true,
      },
      {
        id: 2,
        name: 'Kanban Example',
        done: false,
      },
      {
        id: 3,
        name: 'My own experiments',
        done: false,
      },
    ],
  },
];

ReactDOM.render(<KanbanBoard cards={cardsList} />, document.getElementById('root'));
registerServiceWorker();

eslintからのエラーが表示されるが気にしないで欲しい。
これらはpropsに関するエラーで別途の記事で説明する予定だ。
他のエラーが表示されたらタイピングミスなので、修正しよう。

src/components/KanbanBoard.js
    1 import React, { Component } from 'react';
    2 import List from './List';
    3
    4 class KanbanBoard extends Component {
    5   render() {
    6     return (
    7       <div className="app">
    8         <List
    9           id="todo"
   10           title="To Do"
   11           cards={
  12             this.props.cards.filter((card) => card.status === 'todo')
   13           }
   14         />
   15         <List
   16           id="in-progress"
   17           title="In Progress"
   18           cards={
  19             this.props.cards.filter((card) => card.status === 'in-progress')
   20           }
   21         />
   22         <List
   23           id="done"
   24           title="Done"
   25           cards={
  26             this.props.cards.filter((card) => card.status === 'done')
   27           }
   28         />
   29       </div>
   30     );
   31   }
   32 }
   33
   34 export default KanbanBoard;
src/components/List.js
    1 import React, { Component } from 'react';
    2 import Card from './Card';
    3
    4 class List extends Component {
    5   render() {
   6     const cards = this.props.cards.map((card) => {
    7       return (<Card
    8         id={card.id}
    9         title={card.title}
   10         description={card.description}
   11         tasks={card.tasks}
   12       />
   13       );
   14     });
   15
   16     return (
   17       <div className="list">
  18         <h1>{this.props.title}</h1>
   19         {cards}
   20       </div>
   21     );
   22   }
   23 }
   24
   25 export default List;
src/components/Card.js
    1 import React, { Component } from 'react';
    2 import CheckList from './CheckList';
    3
    4 class Card extends Component {
    5   render() {
    6     return (
    7       <div className="card">
   8         <div className="card__title">{this.props.title}</div>
    9         <div className="card__details">
  10           {this.props.description}
  11           <CheckList cardId={this.props.id} tasks={this.props.tasks} />
   12         </div>
   13       </div>
   14     );
   15   }
   16 }
   17
   18 export default Card;
src/components/CheckList.js
    1 import React, { Component } from 'react';
    2
    3 class CheckList extends Component {
    4   render() {
   5     const tasks = this.props.tasks.map((task) => (
    6       <li className="checklist__task">
    7         <input type="checkbox" defaultChecked={task.done} />
    8         {task.name}
   9         <span className="checklist__task--remove" />
   10       </li>
   11     ));
   12
   13     return (
   14       <div className="checklist">
   15         <ul>{tasks}</ul>
   16       </div>
   17     );
   18   }
   19 }
   20
   21 export default CheckList;

:bulb: anchor-has-contentについて


9ラインのspanタグは本のサンプルではlinkタグだった。
コンテンツを持っていなかったので、eslintエラーが出る。
なぜlinkタグがコンテンツを持ってなければならないのか?
それはSEOと関連がある。
アンカーテキストはSEO的に重要な意味を持つ。
これについては自ら検索してみよう。
ただeslintは本当に優れものだと分かっていただければと思う。
プログラマーに正しい道を教えてくれる道しるべみたいなものだ。

cssファイルはタイピングせずにコピペしよう。

src/index.css
*{
  box-sizing: border-box;
}

html,body,#root {
  height:100%;
  margin: 0;
  padding: 0;
}

body {
  background: #eee;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

h1{
  font-weight: 200;
  color: #3b414c;
  font-size: 20px;
}

ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

.app {
  white-space: nowrap;
  height:100%;
}

.list {
  position: relative;
  display: inline-block;
  vertical-align: top;
  white-space: normal;
  height: 100%;
  width: 33%;
  padding: 0 20px;
  overflow: auto;
}

.list:not(:last-child):after{
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 1px;
  height: 99%;
  background: linear-gradient(to bottom, #eee 0%, #ccc 50%, #eee 100%) fixed;
}

.card {
  position: relative;
  z-index: 1;
  background: #fff;
  width: 100%;
  padding: 10px 10px 10px 15px;
  margin: 0 0 10px 0;
  overflow: auto;
  border: 1px solid #e5e5df;
  border-radius: 3px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}

.card__title {
  font-weight: bold;
  border-bottom: solid 5px transparent;
}

.card__title:before {
  display: inline-block;
  width: 1em;
  content: '▸';
}

.card__title--is-open:before {
  content: '▾';
}

.checklist__task:first-child {
  margin-top: 10px;
  padding-top: 10px;
  border-top: dashed 1px #ddd;
}

.checklist__task--remove:after{
  display: inline-block;
  color: #d66;
  content: "✖";
}

.checklist--add-task {
  border: 1px dashed #bbb;
  width: 100%;
  padding: 10px;
  margin-top: 5px;
  border-radius: 3px;
}

ここまですると次の画面が表示される。

스크린샷 2017-06-22 19.08.20.png

このサンプルではpropsを渡しているだけで、まだstateを扱っていない。
それで(immutable)なのだ。
次の記事でstateについて学ぶ。

13
18
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
13
18