-
-
Save janicduplessis/f513032eb37cdde5d050d9ce8cf0b92a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @flow | |
import React from 'react'; | |
import { | |
ActivityIndicator, | |
Text, | |
TouchableOpacity, | |
View, | |
} from 'react-native'; | |
import Relay from 'react-relay'; | |
type Variables = {[name: string]: mixed}; | |
type Config = { | |
queries: {[name: string]: any}; | |
queriesParams?: ?(props: Object) => Object; | |
fragments: {[name: string]: any}; | |
initialVariables?: Variables; | |
prepareVariables?: (prevVariables: Variables, route: any) => Variables; | |
forceFetch?: bool; | |
onReadyStateChange?: (readyState: any) => void; | |
renderFetched?: ( | |
props: Object, | |
fetchState: { done: bool; stale: bool } | |
) => ?ReactElement<any>; | |
renderLoading?: () => ?ReactElement<any>; | |
renderFailure?: (error: Error, retry: ?() => void) => ?ReactElement<any>; | |
}; | |
// TODO: Make proper loading / failure components. | |
const LoadingView = () => ( | |
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> | |
<ActivityIndicator size="large" /> | |
</View> | |
); | |
const FailureView = ({ error, retry }) => ( | |
<View style={{ paddingTop: 46, alignItems: 'center' }}> | |
<Text>Error</Text> | |
<Text>{error.message}</Text> | |
<TouchableOpacity onPress={retry}> | |
<Text>Try again</Text> | |
</TouchableOpacity> | |
</View> | |
); | |
export function createRenderer( | |
Component: ReactClass<*>, | |
config: Config | |
): ReactClass<*> { | |
return createRendererInternal(Component, { | |
forceFetch: true, | |
renderLoading: () => <LoadingView />, | |
renderFailure: (error, retry) => <FailureView error={error} retry={retry} />, | |
...config, | |
}); | |
} | |
function createRendererInternal( | |
Component: ReactClass<*>, | |
config: Config | |
): ReactClass<*> { | |
const { | |
queries, | |
queriesParams, | |
forceFetch, | |
renderFetched, | |
renderLoading, | |
renderFailure, | |
onReadyStateChange, | |
fragments, | |
initialVariables, | |
prepareVariables, | |
} = config; | |
const RelayComponent = Relay.createContainer(Component, { | |
fragments, | |
initialVariables, | |
prepareVariables, | |
}); | |
class RelayRendererWrapper extends React.Component { | |
state = { | |
queryConfig: this._computeQueryConfig(this.props), | |
}; | |
render() { | |
return ( | |
<Relay.Renderer | |
Container={RelayComponent} | |
forceFetch={forceFetch || false} | |
onReadyStateChange={onReadyStateChange} | |
queryConfig={this.state.queryConfig} | |
environment={Relay.Store} | |
render={({ done, error, props, retry, stale }) => { | |
if (error) { | |
if (renderFailure) { | |
return renderFailure(error, retry); | |
} | |
} else if (props) { | |
if (renderFetched) { | |
return renderFetched({ ...this.props, ...props }, { done, stale }); | |
} else { | |
return <RelayComponent {...this.props} {...props} />; | |
} | |
} else if (renderLoading) { | |
return renderLoading(); | |
} | |
return undefined; | |
}} | |
/> | |
); | |
} | |
componentWillReceiveProps(nextProps: Object) { | |
if (this.props.routeParams !== nextProps.routeParams) { | |
this.setState({ | |
queryConfig: this._computeQueryConfig(nextProps), | |
}); | |
} | |
} | |
_computeQueryConfig(props: Object) { | |
const params = queriesParams ? queriesParams(props) : {}; | |
const queryConfig = { | |
name: `relay-route-${RelayComponent.displayName}`, | |
queries: { ...queries }, | |
params, | |
}; | |
return queryConfig; | |
} | |
} | |
return RelayRendererWrapper; | |
} |
You should avoid the use of dash here: relay-route-${RelayComponent.displayName}
for the name of QueryConfig
it should be
const name = `relay_route_${RelayComponent.displayName}`.replace(/[\(|\)]/g, '_');
parenthesis ()
and dash -
can cause some problems in Graphql
for instance:
Syntax Error GraphQL request (1:25) Expected $, found Name "Search"
1: query relay_route_Relay(Search)($id_0:ID!) {
^
2: node(id:$id_0) {
[ { line: 1, column: 25 } ]
GraphQLError: Syntax Error GraphQL request (1:25) Expected $, found Name "Search"
1: query relay_route_Relay(Search)($id_0:ID!) {
^
2: node(id:$id_0) {
take a look on this: r0b1n/rnrf-relay-renderer#10
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
if I may add a suggestion, I think you should not have
fragments
/initialVariables
/prepareVariables
but instead theComponent
should already be a RelayComponent.It simplifies your code too and it makes things more uncoupled.
it's also more close to https://github.com/relay-tools/react-router-relay