Skip to content

Instantly share code, notes, and snippets.

@ktnyt
Last active September 21, 2017 13:46
Show Gist options
  • Save ktnyt/f2d42a806154c772d0be7ef6f1fe7cad to your computer and use it in GitHub Desktop.
Save ktnyt/f2d42a806154c772d0be7ef6f1fe7cad to your computer and use it in GitHub Desktop.
react-rest memorandum

前提

REST APIとは何か?

  • フロントエンドはビュー
    • f(モデル)→ビュー
    • 外部サービスとの連携
  • バックエンドは永続化
    • リソースの操作に関するロジック
    • アクセス・コントロール

永続化したデータへのアクセスをHTTP上で実現するための取り決めが一定の法則に従って実装されているのがREST API。

バックエンドでのリソースの管理

特定のモデルの取り扱い

永続化したデータへの操作

  1. 一覧の取得 (GET /resource_name)
  2. エントリの取得 (GET /resource_name/:pk)
  3. エントリの追加 (POST /resource_name/:pk + body)
  4. エントリの編集 (PATCH/PUT /resource_name/:pk + body)
  5. エントリの削除 (DELETE /resource_name/:pk)
  6. 一括削除 (DELETE /resource_name)

一覧のフィルタリング

  1. 個数の制限 ?limit=:int
  2. ページネーション (↑とセット) ?offset=:int
  3. 検索 ?search=:string
  4. 時間 ?since=:time&until=:time

などが存在しうる

リレーション

/resource_name/:pk/sub_resource_nameのパスに対して上記の6つの操作ができる。

react-restでどう処理するか

基本的にDOMのツリー構造がリソースのツリー構造と等価になる。

一覧表示など

<Endpoint path='protocols' render={({ protocols }) => protocols.data ? (
  <div>
    <input type='button' value='Add' onClick={event => protocols.handlers.add(/* something */)} />
    <ul>
      {protocols.data.map(protocol => (
        <li>
          <Link to=`/protcol/${protocol.uuid}` />
          {protocol.name}
          <input type='button' value='Delete' onClick={event => protocols.handlers.destroy(protocol.uuid)} />
        </li>
      ))}
    </ul>
  </div>
) : <Loading />} />

サブリソースの取得

<Endpoint path='protocols' pk={protocol.uuid} render={({ protocol }) => (
  <div>
    <h1>{protocol.data.name}</h1>
    <Comments protocol={protocol.data} />
    <Experiments protocol={protocol.data} />
  </div>
)} />

// Comments.render
/// protocols/:pk/comments
<Endpoint path='comments' render={({ comments }) => (
  <ul>
    comments.data.map(comment => (
      <li>
        {comment.text}
        <input type='button' value='Delete' onClick={event => comments.handlers.destroy(comments.uuid)}>
      </li>
    ))
  </ul>
)} />

// Experiments.render
/// pathの先頭を/にすると/experimentsが呼ばれる
<Endpoint path='/experiments' params={{ protocol: protocol.uuid }}>

Contextを使ったパス生成

<Base> // <Endpoints specs={{ groups: {}, projects: {} }}> → state = { selected_group, selected_project } → context
  <Route path='/protocols'>
    <Protocols />
  </Route>
</Base>

class Protocols extends Component {
  contextTypes = {
    labsphere: {
      selected_group: PropTypes.object.isRequired,
      selected_project: PropTypes.objet.isRequired,
    },
  }
  
  render = () => {
    const { selected_group, selected_project } = this.context
    
    <Endpoint path='protocols' params={{ group: seleted_group.uuid, project: selected_project.uuid }}>
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment