yucatio@システムエンジニア

趣味で作ったものいろいろ

"最近の更新"を表示する (STEP 3 : 他のユーザのタスクが見れるタスク管理アプリを作成する - React + Redux + Firebase チュートリアル)

★前回の記事

yucatio.hatenablog.com

/recentUpdatedTodosDashboardに表示します。Dashboardの下にRecentUpdatedTodosコンポーネントを新規作成します。

moment.jsモジュールのインストール

各タスクの更新時間を表示は、「○分前」「○時間前」など、現在からの経過時間を概算で表示します。これにはmoment.jsを利用するので、インストールします。

yarn add moment

"最近の更新”の表示

Dashboardの下にRecentUpdatedTodosコンポーネントを新規作成し、さらにその下にUserUpdatedTodoコンポーネントを作成します。

src/components/Dashboard.js

// 前略
import RecentUpdatedTodos from './RecentUpdatedTodos'  // 追加
 
const Dashboard = () => (
  <div>
    <RecentUpdatedTodos />
  </div>
)

// 後略

src/components/RecentUpdatedTodos.js (新規作成) (実行前にコメントは削除してください)

import React from 'react'
import { compose } from 'redux'
import { connect } from 'react-redux'
import { firebaseConnect, isEmpty, isLoaded } from 'react-redux-firebase'
import PropTypes from 'prop-types'
import UserUpdatedTodos from './UserUpdatedTodo'

const RecentUpdatedList = (todos) => {
  if (!isLoaded(todos)) {
    return <div>読み込み中…</div>
  }
  if (isEmpty(todos)) {
    return <div>データがありません。</div>
  }
  return (
    <ul>
      {todos.map(({key, value:todo}) =>  // #4
        <UserUpdatedTodos  key={key} {...todo}/>
      )}
    </ul>
  )
}

let RecentUpdatedTodos = ({todos}) => {
  return (
    <div>
      <h1>最近の更新</h1>
      {RecentUpdatedList(todos)}
    </div>
  )
}
RecentUpdatedTodos.propTypes = {
  todos: PropTypes.arrayOf(
    PropTypes.shape({
      key: PropTypes.string.isRequired,
      value: PropTypes.object.isRequired,
    })
  ),
}

const firebaseQueries = ({uid}) => (
  [
    {path: `recentUpdatedTodos`, type: 'once', queryParams: [ 'orderByChild=_updatedAt', 'limitToLast=10' ]}  // #1
  ]
)

const mapStateToProps = ({firebase: {ordered : {recentUpdatedTodos}}}) => {  // #2
  return {
    todos: recentUpdatedTodos && recentUpdatedTodos.reverse()  // #3
  }
}

RecentUpdatedTodos = compose(
  firebaseConnect(firebaseQueries),
  connect(
   mapStateToProps
))(RecentUpdatedTodos)

export default RecentUpdatedTodos;
  • 並び替えられたデータはfirebase.orderedで取得できます(#2)。
  • /recentUpdatedTodosonceで取得します(#1)。_updatedAtの昇順で並び替え、最後の10件を取得します。
  • Viewで降順で表示するため、データが存在する場合はreverseして逆順に並び替えます(#3)。
  • 並び替えられたデータは、{key: recentUpdatedTodosのキー, value: recentUpdatedTodosの値}というオブジェクトの配列になっているので、todos.mapで各ノードのキーと値が入ったオブジェクトを取得します(#4)。

src/components/UserUpdatedTodo.js (新規作成)

import React from 'react'
import { Link } from 'react-router-dom'
import moment from 'moment'
import 'moment/locale/ja'  // #1
import PropTypes from 'prop-types'

const UserUpdatedTodo = ({text, eventType, uid, displayName, _updatedAt}) => (
  <li>
    <Link to={`/users/${uid}/todos`}>{displayName}</Link>さんが {text} を{ eventType === 'CREATE' ? '作成' : '更新'}  {/* #2 */}
    しました。 ({ moment(_updatedAt).fromNow()})  {/* #3 */}
  </li>
)

UserUpdatedTodo.propTypes = {
  text: PropTypes.string.isRequired,
  eventType: PropTypes.string.isRequired,
  uid: PropTypes.string.isRequired,
  displayName: PropTypes.string.isRequired,
  _updatedAt: PropTypes.number.isRequired
}

export default UserUpdatedTodo;
  • import 'moment/locale/ja’でmoment.jsの日本語化をします(#1)。
  • displayNameに、そのユーザのタスク一覧へのリンクを貼ります(#2)。
  • moment#fromNow()で経過時間を概算を取得します(#3)。

preserveOnLogoutへの設定追加

react-redux-firebaseのpreserveOnLogoutの設定も忘れずに行います。

src/index.js

const createStoreWithFirebase = compose(
  applyMiddleware(thunk.withExtraArgument({getFirebase})),
  reactReduxFirebase(firebase, {userProfile: 'users', preserveOnLogout: ['todos', 'users', 'recentUpdatedTodos']})  // 変更
)(createStore);

動作確認

http://localhost:3000/ を表示します。

f:id:yucatio:20181028225616p:plain

最近作成更新したタスクが、新しいものが上になるように表示されました。

ユーザ名をクリックします。

f:id:yucatio:20181029134921p:plain

ユーザのタスク一覧に遷移します。

ログアウトします。

f:id:yucatio:20181029140124p:plain

ログアウトしても最新の更新一覧が表示されます。

おめでとうございます!これでSTEP 3の全ての機能が実装できました!

★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com