2016-04-18 3 views
4

Je commence avec Relay et essaye de faire fonctionner correctement mon routage. Malheureusement, je n'ai pas beaucoup de chance.Comment faire fonctionner Relay et React Routing correctement?

Voici l'erreur que je reçois:

Uncaught TypeError: Component.getFragment is not a function

Voici le code que j'ai pour votre référence:

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; 

MISE À JOUR

J'ai fait quelques changements suggérés par freiksenet comme ci-dessous. Mais cela soulève les deux questions suivantes:

  1. Que se passerait-il lorsque je change la route et un autre que Home composant obtient affichés par le composant App?
  2. Je reçois maintenant cette erreur:

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

Voici les changements:

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')} 
     } 
    ` 
    } 
}); 
+0

L'erreur signifie qu'elle ne sait pas ce qu'est 'Component'. Vous devrez l'importer de la même manière que vous avez importé 'App' et' Home'. Je suppose que l'erreur est générée sur le fichier 'index'? – Chris

+0

@Moon Réponse à votre UPDATE 1: Question 2: Vous n'avez transmis aucune requête pour le composant 'Home'. Dans le fichier index.jsx, changez 'en requêtes = {AppQueries}'. Question 1: Comme @freiksenet l'a déjà mentionné, 'App' ne doit pas nécessairement être conteneur. Les autres composants rendus par 'App' n'ont besoin que de fragments nécessaires. –

Répondre

4

Les définitions de fragment n'obtiennent pas réellement des composants en tant qu'arguments, mais une mappe de variables du conteneur, il suffit de les utiliser pour avoir des fragments conditionnels basés sur des valeurs de variables.

Les requêtes d'acheminement de relais n'acceptent aucun argument.

Voici les modifications à apporter.

Les requêtes d'acheminement dans le Relais ont juste besoin de spécifier la requête racine que vous allez récupérer dans cette route, sans le fragment.

index.jsx

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

votre composant App ne fait utiliser pas de données de relais, de sorte que vous pouvez simplement exporter composante normale au lieu de récipient.

export default class App extends Component { 

Si vous devez passer des données de relais à, vous n'avez pas besoin d'inclure des fragments d'enfants, parce que l'inclusion des fragments est nécessaire uniquement lorsque vous rendez directement d'autres conteneurs que les enfants directs (et non comme cela. props.children).

Ensuite, dans le routeur, vous devez déplacer les requêtes vers la page d'accueil.

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

Merci beaucoup pour la réponse. J'ai mis à jour mon code comme suggéré et ensuite mis à jour ma question avec de nouvelles observations. – Moon

+0

@Moon Aha. Il semble que j'ai mal compris ce que vous essayez de faire un peu. Corrigé maintenant. – freiksenet