如何让 Relay 和 React Routing 正常工作?

How to make Relay and React Routing work properly?

我开始使用 Relay 并尝试使我的路由正常工作。 不幸的是,我运气不佳。

这是我收到的错误:

Uncaught TypeError: Component.getFragment is not a function

这是我提供的代码供您参考:

index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import Relay from 'react-relay';
import {Router, Route, IndexRoute, browserHistory} from 'react-router';
import {RelayRouter} from 'react-router-relay';

import App from './modules/app';
import Home from './modules/home';

const AppQueries = {
  store: (Component) => Relay.QL `query {
    store {
      ${Component.getFragment('store')}
    }
  }`
};

ReactDOM.render(
  <RelayRouter history={browserHistory}>
    <Route path='/' component={App} queries={AppQueries}>
      <IndexRoute component={Home}/>
    </Route>
  </RelayRouter>, 
document.getElementById('ch-root'));

app.jsx

import React, {Component} from 'react';
import Relay from 'react-relay';
import Header from './ui/header';
import Footer from './ui/footer';

class App extends Component {
  render() {
    return (
      <div id="ch-container">
        <Header/>
        <section id="ch-body">
          {this.props.children}
        </section>
        <Footer/>
      </div>
    );
  }
}

App = Relay.createContainer(App, {
  fragments: {
    store: (Component) => Relay.QL `
      fragment on Store {
        ${Component.getFragment('store')}
      }
     `
  }
});

export default App;

home.jsx

import React, {Component} from 'react';
import Relay from 'react-relay';
import Loader from './ui/loader';
import AccountSelector from './account/account-selector';

const APP_HOST = window.CH_APP_HOST;
const CURR_HOST = `${window.location.protocol}//${window.location.host}`;

class Home extends Component {
  state = {
    activeAccount: null,
    loading: true
  }

  render() {
    const {activeAccount, loading} = this.state;

    if (loading) {
      return <Loader/>;
    }

    if (!activeAccount && !loading) {
      return <AccountSelector/>;
    }

    return (
      <h1>Hello!</h1>
    );
  }
}

Home = Relay.createContainer(Home, {
  fragments: {
    store: () => Relay.QL `
      fragment on Store {
        accounts {
          unique_id,
          subdomain
        }
      }
     `
  }
});

export default Home;

更新

我按照 freiksenet 的建议进行了一些更改,如下所示。但这引发了以下两个问题:

  1. 当我更改路由并且 Home 以外的组件被 App 组件渲染时会发生什么?
  2. 我现在收到这个错误:

Warning: RelayContainer: Expected prop store to be supplied to Home, but got undefined. Pass an explicit null if this is intentional.

更改如下:

index.jsx

const AppQueries = {
  store: () => Relay.QL `query {
    store 
  }`
};

app.jsx

import Home from "./home";

...

App = Relay.createContainer(App, {
  fragments: {
    store: () => Relay.QL `
      fragment on Store {
        ${Home.getFragment('store')}
      }
     `
  }
});

Fragment定义实际上并没有获取Components作为参数,而是容器的变量映射,你只需要使用它们来根据变量值有条件的fragments。

中继路由查询不接受任何参数。

这是您需要进行的更改。

中继中的路由查询只需要指定您要在此路由中检索的根查询,无需分片。

index.jsx

const AppQueries = {
  store: () => Relay.QL `query {
    store 
  }`
};

你的App组件实际上没有使用任何中继数据,所以你可以只导出普通组件而不是容器。

export default class App extends Component {

如果你需要传递一些中继数据给它,你不需要包含子片段,因为只有当你直接将其他容器渲染为直接子容器时才需要包含片段(而不是 this.props.children).

然后在 Router 中您需要将查询移动到 Home。

ReactDOM.render(
  <RelayRouter history={browserHistory}>
    <Route path='/' component={App}>
      <IndexRoute component={Home} queries={AppQueries} />
    </Route>
  </RelayRouter>, 
document.getElementById('ch-root'));