I am starting out with Relay and trying to make my routing work properly. Unfortunately, I am not having much of luck.
Here is the error I am getting:
Uncaught TypeError: Component.getFragment is not a function
Here is the code I have for your reference:
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;
UPDATE
I made few changes suggested by freiksenet
as below. But that raises the following two issues:
Home
gets rendered by the App
component?Warning: RelayContainer: Expected prop
store
to be supplied toHome
, but gotundefined
. Pass an explicitnull
if this is intentional.
Here are the changes:
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 definitions don't actually get Components as arguments, but a map of variables of the container, you only need to use them to have conditional fragments based on variable values.
Relay Route queries don't accept any arguments.
Here are the changes you need to make.
Route queries in Relay just need to specify the root query you are going to retrieve in this route, without the fragment.
index.jsx
const AppQueries = {
store: () => Relay.QL `query {
store
}`
};
Your App component actually doesn't use any relay data, so you can just export normal component instead of container.
export default class App extends Component {
If you'd need to pass some Relay data to it, you don't need to include child fragments, because fragments inclusion is only needed when you directly render other containers as direct children (not as this.props.children).
Then in Router you need to move the queries to Home.
ReactDOM.render(
<RelayRouter history={browserHistory}>
<Route path='/' component={App}>
<IndexRoute component={Home} queries={AppQueries} />
</Route>
</RelayRouter>,
document.getElementById('ch-root'));