- 
      
 - 
        
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.