web-dev-qa-db-ja.com

マルチページアプリでReactを使用する

私はReactで遊んでいますが、これまでのところ本当に気に入っています。 NodeJSでアプリを構築していますが、アプリケーション全体のインタラクティブコンポーネントのいくつかにReactを使用したいと思います。私はそれを単一ページのアプリにしたくない。

次の質問に答えるウェブ上の情報はまだ見つかりません。

マルチページアプリでReactコンポーネントを分割またはバンドルするにはどうすればよいですか?

現在、アプリの一部のセクションでコンポーネントをロードすることはありませんが、すべてのコンポーネントは1つのファイルにあります。

これまでのところ、ReactがレンダリングするコンテナーのIDを検索して、条件ステートメントを使用してコンポーネントをレンダリングしようとしています。 Reactのベストプラクティスが100%確実ではありません。こんな感じです。

if(document.getElementById('a-compenent-in-page-1')) {
    React.render(
        <AnimalBox url="/api/birds" />,
        document.getElementById('a-compenent-in-page-1')
    );
}

if(document.getElementById('a-compenent-in-page-2')) {
    React.render(
        <AnimalBox url="/api/cats" />,
        document.getElementById('a-compenent-in-page-2')
    );
}

if(document.getElementById('a-compenent-in-page-3')) {
    React.render(
        <AnimalSearchBox url="/api/search/:term" />,
        document.getElementById('a-compenent-in-page-3')
    );
}

私はまだドキュメントを読んでいますが、マルチページアプリに必要なものがまだ見つかりません。

前もって感謝します。

101
Jose Carrillo

現在、私は似たようなことをしています。

アプリケーションは完全なReactアプリではありません。私はReactを使用して、autarkであるCommentBoxなどの動的なものを使用しています。そして、特別なパラメータで任意のポイントに含めることができます。

ただし、すべてのサブアプリはロードされ、単一のファイルall.jsに含まれているため、ブラウザーでページ間でキャッシュできます。

アプリをSSRテンプレートに含める必要がある場合、クラス「__react-root」と特別なID(レンダリングされるReactアプリの名前)を持つDIVを含める必要があります。

ロジックは本当に簡単です。

import CommentBox from './apps/CommentBox';
import OtherApp from './apps/OtherApp';

const APPS = {
  CommentBox,
  OtherApp
};

function renderAppInElement(el) {
  var App = APPS[el.id];
  if (!App) return;

  // get props from elements data attribute, like the post_id
  const props = Object.assign({}, el.dataset);

  ReactDOM.render(<App {...props} />, el);
}

document
  .querySelectorAll('.__react-root')
  .forEach(renderAppInElement)

<div>Some Article</div>
<div id="CommentBox" data-post_id="10" class="__react-root"></div>

<script src="/all.js"></script>

編集

Webpackはコード分割とLazyLoadingを完全にサポートしているため、すべてのアプリを1つのバンドルに読み込む必要はなく、分割してオンデマンドで読み込む例を含めるのは理にかなっていると思いました。

import React from 'react';
import ReactDOM from 'react-dom';

const apps = {
  'One': () => import('./One'),
  'Two': () => import('./Two'),
}

const renderAppInElement = (el) => {
  if (apps[el.id])  {
    apps[el.id]().then((App) => {
      ReactDOM.render(<App {...el.dataset} />, el);
    });
  }
}
74
webdeb

Webpack.config.jsファイルでアプリケーションのいくつかのエントリポイントを提供できます。

var config = {
  entry: {
    home: path.resolve(__dirname, './src/main'),
    page1: path.resolve(__dirname, './src/page1'),
    page2: path.resolve(__dirname, './src/page2'),
    vendors: ['react']
  },
 output: {
    path: path.join(__dirname, 'js'),
    filename: '[name].bundle.js',
    chunkFilename: '[id].chunk.js'
  },
}

次に、srcフォルダーに3つの異なるhtmlファイルとそれぞれのjsファイルを含めることができます(page1の例):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Page 1</title>
</head>
<body>
  <div id="app"></div>
  <script src="./vendors.js"></script>
  <script src="./page1.bundle.js"></script>
</body>
</html>

JavaScriptファイル:

import React from 'react'
import ReactDom from 'react-dom'
import App from './components/App'
import ComponentA from './components/ReactComponentA'
ReactDom.render(<div>
                  <App title='page1' />
                  <ReactComponentA/>
                 </div>, document.getElementById('app'))

その後、異なるReactコンポーネントを各ページにロードできます。

47
Cocomico

編集:2015年11月1日

私はアプリケーションを一から構築し、学習しながら学習していますが、あなたが探しているのは React-Router です。 React-Routerは、コンポーネントを特定のURLにマップします。例えば:

render((
    <Router>
        <Route path="/" component={App}>
            <Route path="api/animals" component={Animals}>
               <Route path="birds" component={Birds}/>
               <Route path="cats" component={Cats}/>
            </Route>
        </Route>
        <Route path="api/search:term" component={AnimalSearchBox}>
    </Router>
), document.body)

検索の場合、「term」はAnimalSearchBoxのプロパティとしてアクセスできます。

componentDidMount() {
    // from the path `/api/search/:term`
    const term = this.props.params.term
}

やってみよう。 This チュートリアルは、このトピックおよび他の関連トピックの理解に関して、私を一番上に置いたものです。

元の答えは次のとおりです。

私はここで同じ答えを探して自分の道を見つけました。 this 投稿があなたに刺激を与えているかどうかを確認してください。アプリケーションが私のようなものである場合、その領域はほとんど変化せず、本体のみが異なります。アプリケーションの状態に基づいて異なるウィジェットをレンダリングすることを担当するウィジェットを作成できます。フラックスアーキテクチャを使用すると、ボディウィジェットの切り替え状態を変更するナビゲーションアクションをディスパッチし、ページのボディのみを効果的に更新できます。

それが私が今試みているアプローチです。

32
Scott

CMSを使用していますか?彼らはあなたのアプリケーションを壊す可能性のあるURLの変更を好む傾向があります。

別の方法は React Habitat のようなものを使用することです。

これを使用して、コンポーネントを登録すると、それらは自動的にdomに公開されます。

コンポーネントの登録:

container.register('AnimalBox', AnimalBox);
container.register('AnimalSearchBox', AnimalSearchBox);

そして、彼らはあなたのdomでこのように利用可能です:

<div data-component="AnimalBox"></div>

<div data-component="AnimalSearchBox"></div>

上記は、reactコンポーネントに自動的に置き換えられます。

その後、コンポーネントにもプロパティ(またはプロパティ)を自動的に渡すことができます。

<div data-component="AnimalBox" data-prop-size="small"></div>

これにより、sizeがコンポーネントの小道具として公開されます。 json、配列、int、floatなどの他の型を渡すための 追加オプション があります。

11
jennas

この質問が聞かれてからしばらく経ちましたが、これが誰かの助けになることを願っています。

@Cocomicoが述べたように、webpack.config.jsファイルでアプリケーションのいくつかのエントリポイントを提供できます。静的ページにReactコンポーネントを追加できる単純なWebpackセットアップ(複数のエントリポイントのアイデアに基づく)を探している場合は、これを使用することを検討してください: https:// github .com/przemek-nowicki/multi-page-app-with-react

1
Przemek Nowicki