saitoxu.io

AboutTwitterGitHub

TODOアプリでReact Routerを使ってみる

April 02, 2017

前回作った TODO アプリに、 react-router を使ってルーティングを組み込んでみます。

できたものはこちら ↓

todo-app-2

1. コンポーネントの構成

コンポーネントの構成は次のような形にします。

Components

また、ルーティングは次のとおりとします。

  • / トップページ
  • /:id 各 TODO の詳細ページ

各 TODO のリンクをクリックすると、その詳細が表示されるという簡単なものです。

2. 実装

前回はちょっとややこしい作りにしてましたが、今回はAppコンポーネントだけで state 管理をし、他のコンポーネントは基本レンダリングするだけにしました。

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>
)
}
}
view raw App.js hosted with ❤ by GitHub

※一応、残りの主要なコンポーネントもGistにあげてます。

3. おわりに

TODO アプリに react-router を使ってルーティングを組み込んでみました。

次は Redux を触ってみる予定です。