Skip to content

Instantly share code, notes, and snippets.

@IKKO-Ohta
Last active August 16, 2018 14:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IKKO-Ohta/664da0e245a4fbcc8c7202fe79852189 to your computer and use it in GitHub Desktop.
Save IKKO-Ohta/664da0e245a4fbcc8c7202fe79852189 to your computer and use it in GitHub Desktop.
react-routingについて
import React from "react";
import { render } from "react-dom";
import { Router, Route, hashHistory } from "react-router";
import Login from "./Login";
import Signup from "./Signup";
import Rooms from "./Rooms";
import Room from "./Room";
import mainBar from "./mainBar"
import Project from "./Project"
import Projects from "./Projects"
import MarkdownEditorUI from "./MarkdownEditorUI";
import data from "./firebase.json";
import firebase from "firebase/firebase-browser";
// Routingの定義
const appRouting = (
<Router history={hashHistory}>
<Route path="/">
<Route path="login" component={Login} />
<Route path="signup" component={Signup} />
<Route path = "projects" component={Projects}>
<Route path=":projectId" component={Project}>
<Route path="mainBar" component={mainBar}>
<Route path="MarkdownEditorUI" component={MarkdownEditorUI} />
<Route path="rooms" component={Rooms}>
<Route path=":roomId" component={Room} />
</Route>
</Route>
</Route>
</Route>
</Route>
</Router>
);
// Routingの初期化
if (!location.hash.length) {
location.hash = "#/login";
}
// Initialize Firebase
const config = data;
firebase.initializeApp(config);
// Applicationをrendering
render(appRouting, document.getElementById("app"));
import React from "react";
import { Link } from "react-router"
const IMAGE_STYLE = {
width: 400,
fontSize: 48
};
/**
* @extends {React.Component}
* @constructor
*/
export default class Project extends React.Component {
/**
* [constructor description]
* @param {[prohectName:string, thumbnail:string]} props 今のところサムネイルは埋め込み
*/
constructor(props){
super(props);
this.state = {
projectName: this.props.params.projectName,
projectId: this.props.params.projectId,
thumbnail: "./dist/img/Necronomicon_prop.jpg"
};
}
/**
* [render description]
* @return {jsx} 左ペインに一覧を書き、右ペインにその子要素を表示する
*/
render() {
const { projectName, projectId, thumbnail } = this.state;
let linkUrl = projectId + "/MarkdownEditorUI"
return (
<div className="window">
<div className="window-content">
<Link to = {linkUrl} >
<img src = { thumbnail } style={IMAGE_STYLE}/>
</Link>
</div>
</div>
);
}
}

プロジェクトごとに、独自に拡張したエディタ・サービスを提供したい。(ex.overleaf)

プロジェクトを作成して、firebase dbに新しく項目を保存できるようにした。
今度は、このdbのさらに下層にエディタで編集した記事や画像を保存できるようにしたい。
それにともなって、routing構造も:projectIdの下にエディタ機能の本体であるmainBarも配置するのが自然だと考え、app.jsxのようにroutingを設定した。

しかし、project.jsx側で

let linkUrl =  projectId + "/mainBar"
return (
 <link to = {linkUrl}> hogehoge </link>
 )

としても

Warning: [react-router] Location "-LJg3eOlJLhogeHogehoge/mainBar" did not match any routes

となる。

  • どのように指定すれば正しい結果が得られるか。
  • このようなreact-routerの情報は、公式ドキュメントのどこを参照すれば入手できるか。
  • もし、日本語でreact-router v3についてより詳しく説明された書物があれば、それも合わせて教えてほしい。
@joe-re
Copy link

joe-re commented Aug 13, 2018

  • どのように指定すれば正しい結果が得られるか。
    Link Componentのtoには相対パスは渡せないようなので、絶対パスを指定するようにすれば動くかと思います。
let linkUrl = `/projects/${projectId}/mainBar/MarkdownEditorUI`

参考: https://github.com/ReactTraining/react-router/blob/v3/docs/API.md#link

If it's a string it represents the absolute path to link to, e.g. /users/123 (relative paths are not supported).

  • このようなreact-routerの情報は、公式ドキュメントのどこを参照すれば入手できるか。

上に貼った参考リンクも公式ですが、基本的には公式のdocsを見るのが良いと思います。

https://github.com/ReactTraining/react-router/tree/v3/docs

何か問題に遭遇した時は同じようにハマっている人もいるかも知れないので、githubのissueを探してみることも僕はよくやります。

  • もし、日本語でreact-router v3についてより詳しく説明された書物があれば、それも合わせて教えてほしい。

すみません、日本語の資料については僕もよく知りません。。
OSSによっては、日本のコミュニティで公式のdocs翻訳しているものもありますが、react routerにはないようです。
どちらにせよ、OSSのプロジェクトについては英語が一次情報になることが多いので、あまり抵抗を持たずに読んでいくようにした方があとになっても楽かなぁ、と思います。

@joe-re
Copy link

joe-re commented Aug 13, 2018

また、mainBarなどの情報は共通してrenderingされるものの、routingには関係なのでURLには現れない方が良いかなぁと思います。
ブラウザで表示するURLも、基本的にはリソース指向で考えた方が良いです。

@joe-re
Copy link

joe-re commented Aug 13, 2018

簡単ですが、動作確認の為に書いたコードを貼っておきますので、ご参考にしてください 🙇‍♂️

import React from 'react';
import { render } from 'react-dom';
import { Link, Router, Route, hashHistory } from 'react-router';

const Home = (p) =>
  <div>
    <h1>Home</h1>
    <ol>
      <li><Link to="/login">Login</Link></li>
      <li><Link to="/signup">Signup</Link></li>
      <li><Link to="/projects">Projects</Link></li>
    </ol>
    {p.children}
  </div>;

const Login = () => <div><h2>Login</h2></div>;

const Signup = () => <div><h2>Signup</h2></div>;

const Projects = (p) =>
  <div>
    <h2>Projects</h2>
    <ol>
      <li><Link to="/projects/1">Project1</Link></li>
      <li><Link to="/projects/2">Project2</Link></li>
      <li><Link to="/projects/3">Project3</Link></li>
    </ol>
    {p.children}
  </div>;

const Project = (p) => {
  const baseUrl = `/projects/${p.params.projectId}`;
  return (
    <div>
      <h3>Project</h3>
      <p>ProjectId: {p.params.projectId}</p>
      <ol>
        <li><Link to={`${baseUrl}/MarkdownEditorUI`}>MarkdownEditorUI</Link></li>
        <li><Link to={`${baseUrl}/rooms/1`}>Room1</Link></li>
        <li><Link to={`${baseUrl}/rooms/2`}>Room2</Link></li>
        <li><Link to={`${baseUrl}/rooms/3`}>Room3</Link></li>
      </ol>
      {p.children}
    </div>
  );
};

const mainBar = (p) =>
  <div>
    <h4>MainBar</h4>
    {p.children}
  </div>;

const MarkdownEditorUI = (p) =>
  <div>
    <h5>MarkdownEditorUI</h5>
    {p.children}
  </div> ;

const Rooms = (p) => <div><h5>Rooms{p.children}</h5></div>;

const Room = (p) =>
  <div>
    <h5>Room</h5>
    <p>RoomId: {p.params.roomId}</p>
  </div>;

const routing =
  <Router history={hashHistory}>
    <Route path="/" component={Home}>
      <Route path="login" component={Login} />
      <Route path="signup" component={Signup} />
      <Route path = "projects" component={Projects}>
        <Route path = ":projectId" component={Project}>
          <Route component={mainBar}>
            <Route path="MarkdownEditorUI" component={MarkdownEditorUI} />
            <Route path="rooms" component={Rooms}>
              <Route path=":roomId" component={Room} />
            </Route>
          </Route>
        </Route>
      </Route>
    </Route>
  </Router>;
render(routing, document.getElementById('root'));

@IKKO-Ohta
Copy link
Author

ありがとうございます。
少し時間をいただいて全体について検討しました。

  • [1]の渡し方
    確かにドキュメントに書いてありました。これは絶対パスでないといけなかったのですね……。
    実際これで動くことを確かめました。

  • [2][3] react-router v3について
    了解しました。これらをできる範囲で読み込んでいきます。
    読む量がとても多くてちょっとめげそうですが、分からない部品からひとつひとつ積み上げるしかないですね。精進します。

  • URLには現れないほうが良い、リソース志向で考えるべきだ
    これについては疑問があります。
    野口さんが仰っていることは、App.jsxの構成は

/
├ login
├ signup
├ projects
│ └ :projectID
└  mainBar
    ├  MarkdownEditorUI
    └ rooms
        └ :roomID

と書いたほうがよい、という理解です。

その一方で、Firebaseの構成はこのapp.jsxのルート構造に従って、
1案:

ROOT
├ project-main
│ └ firebase-hashID
│   ├ description
│   ├ abstract
│   └ notebook
└ projects
  └ firebase-hashID
    ├ description
    └ member 

などと書くのが良いということですか。あるいは、
2案:

ROOT
└ projects
  └ firebase-hashID
    ├ description
    ├ member 
    └ project-main
      ├ firebase-hashID
      ├ description
      ├ abstract
      └ notebook

などと、こちらはあくまでもサービスの基本的な使われ方を想定して設計してもよいということですか。
これはmarkdownEditor UIでabstractページや、拡張改造を施したチャットルーム機能でnotebookを書いたりするアプリケーションです。そういうわけで、私としては2案のほうが直観的にみえるし、データをfirebaseで参照するときにもずっと楽だと考えます。僕の予想では、app上の構成としては野口さんが示したような書き方で書き、firebaseは(それとは構造が異なるけれども)2案のような仕方で書くのが良いのかな、と思いました。お手数ですが、もしお時間許しましたら、野口さんの見解をお聞かせ願えますか。
よろしくお願いします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment