TODOアプリでReact Routerを使ってみる
April 02, 2017
前回作った TODO アプリに、 react-router を使ってルーティングを組み込んでみます。
できたものはこちら ↓
1. コンポーネントの構成
コンポーネントの構成は次のような形にします。
また、ルーティングは次のとおりとします。
/
トップページ/:id
各 TODO の詳細ページ
各 TODO のリンクをクリックすると、その詳細が表示されるという簡単なものです。
2. 実装
前回はちょっとややこしい作りにしてましたが、今回はApp
コンポーネントだけで state 管理をし、他のコンポーネントは基本レンダリングするだけにしました。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react' | |
import { Link, Route, Switch } from 'react-router-dom' | |
import Form from './Form' | |
import Todo from './Todo' | |
import TodoList from './TodoList' | |
const Top = () => ( | |
<div>Top</div> | |
) | |
const NoMatch = ({ location }) => ( | |
<div> | |
<h3>No match for <code>{location.pathname}</code></h3> | |
</div> | |
) | |
export default class App extends Component { | |
constructor() { | |
super() | |
this.state = { | |
todos: [] | |
} | |
} | |
handleSubmit(e) { | |
e.preventDefault() | |
const title = e.target.elements[0].value | |
if (!title) { | |
return | |
} | |
const desc = e.target.elements[1].value | |
const todos = this.state.todos.slice() | |
todos.push({ | |
title: title, | |
desc: desc, | |
done: false | |
}) | |
this.setState({ todos: todos }) | |
e.target.elements[0].value = null | |
e.target.elements[1].value = null | |
} | |
toggleStatus(e) { | |
e.preventDefault() | |
const id = parseInt(e.currentTarget.getAttribute('data-id'), 10) | |
const todo = this.state.todos[id] | |
const todos = this.state.todos.slice() | |
todos[id] = { | |
title: todo.title, | |
desc: todo.desc, | |
done: !todo.done | |
} | |
this.setState({ todos: todos }) | |
} | |
render() { | |
return ( | |
<div> | |
<Link to="/">Top</Link> | |
<Form onSubmit={this.handleSubmit.bind(this)} /> | |
<TodoList todos={this.state.todos} onClick={this.toggleStatus.bind(this)} /> | |
<Switch> | |
<Route exact path="/" component={Top} /> | |
<Route exact path="/:id" render={(props) => { | |
const todos = this.state.todos | |
return ( | |
<Todo | |
todos={todos} | |
{...props} | |
/> | |
) | |
}} /> | |
<Route component={NoMatch} /> | |
</Switch> | |
</div> | |
) | |
} | |
} |
※一応、残りの主要なコンポーネントもGistにあげてます。
3. おわりに
TODO アプリに react-router を使ってルーティングを組み込んでみました。
次は Redux を触ってみる予定です。