-
-
Save fdecampredon/f337605e393a5b032b85 to your computer and use it in GitHub Desktop.
import React from 'react'; | |
import { container } from 'redux-relay'; | |
@container({ | |
variablesFromState: (state) => ({myVariable: state.myState}) | |
fragments: { | |
Relay.QL` | |
viewer { | |
myFunc($myVariable) { | |
foo, | |
bar | |
} | |
} | |
` | |
} | |
}); | |
class Container extends React.Component { | |
render() { | |
const { viewer } = this.props; | |
.... | |
} | |
} | |
export default Container; |
import Relay from 'react-relay'; | |
import React from 'react'; | |
import {Provider as ReactReduxProvider } from 'react-redux'; | |
let store; | |
function setStore(value) { | |
store = value; | |
} | |
const containerProperties = { | |
'getFragmentNames': true, | |
'getQueryNames': true, | |
'hasFragment': true, | |
'hasVariable': true, | |
'getFragment': true, | |
'getQuery': true, | |
'contextTypes': false, | |
'displayName': false, | |
'moduleName': false | |
}; | |
function createLazyContainer(Container, variablesFromState, fragments) { | |
let relayContainer; | |
const getRelayContainer = () => { | |
if (!relayContainer) { | |
const {forceFetch, ...initialVariables} = variablesFromState(store.getState()); //eslint-disable-line no-unused-vars | |
relayContainer = Relay.createContainer(Container, { initialVariables, fragments }); | |
} | |
return relayContainer; | |
}; | |
const lazyContainer = (props, context) => { | |
const Container = getRelayContainer(); | |
return new Container(props, context); | |
}; | |
for (let property of Object.keys(containerProperties)) { | |
const isFunction = containerProperties[property]; | |
if (isFunction) { | |
Object.defineProperty(lazyContainer, property, { | |
value: function (...args) { | |
const container = getRelayContainer(); | |
return container[property](...args); | |
}, | |
enumerable: true, | |
configureable: true, | |
writable: true | |
}); | |
} else { | |
Object.defineProperty(lazyContainer, property, { | |
get: () => getRelayContainer()[property], | |
set: (val) => getRelayContainer()[property] = val, | |
enumerable: true, | |
configureable: true | |
}); | |
} | |
} | |
return lazyContainer; | |
} | |
export function container({variablesFromState, fragments}) { | |
return function (Component) { | |
if (variablesFromState) { | |
class Container extends React.Component { | |
static displayName = `ReduxRelay(${Component.displayName || Component.name})` | |
componentDidMount() { | |
this._subscription = store.subscribe(() => { | |
const { forceFetch, ...variables } = variablesFromState(store.getState()); | |
if (forceFetch) { | |
this.props.relay.forceFetch(variables); | |
} else { | |
this.props.relay.setVariables(variables); | |
} | |
}); | |
} | |
componentWillUnmount() { | |
this._subscription.dispose(); | |
} | |
render() { | |
return <Component {...this.props} />; | |
} | |
} | |
return createLazyContainer(Container, variablesFromState, fragments); | |
} else { | |
return Relay.createContainer(Component, { fragments }); | |
} | |
}; | |
} | |
export const Provider = ({store, ...props}) => { | |
setStore(store); | |
return <ReactReduxProvider store={store} {...props} />; | |
}; | |
import { Provider } from 'redux-relay'; | |
import Relay from 'react-relay'; | |
import ReactDOM from 'react-dom'; | |
import configureStore from './store'; | |
import Container from './Container'; | |
import route from './route'; | |
const store = configureStore(); | |
ReactDOM.render( | |
<Provider store={store}> | |
<Relay.RootContainer route={route} Component={Container} /> | |
</Provider> | |
); |
I like this way of combining relay and redux, was looking at implementing something similar. You had any issues using a system like this in production?
implemented pretty much the same logic, but can't get rid of a warning:
Warning: RelayContainer: component `...` was rendered with variables that differ from the variables used to fetch fragment `...`
Did you encountered this one too ?
Thanks for putting this together! Just added babel-plugin-transform-decorators-legacy
but now I'm getting TypeError: Cannot read property 'getState' of undefined
(line 27 of redux-relay
). It throws the error before the modified provider has a chance to add the state. It looks like it trying to get the state before runtime?
This is amazing. Thanks for sharing. I asked a question on stack overflow about how to accomplish this (http://stackoverflow.com/questions/41069179/retrieving-variables-for-a-relay-query-fragment-from-an-external-store) and answered my own question with a link to this.
I think better place for leaving feedback, will be this issue reduxjs/redux#464
Because there are a lot of brilliant peoples.