Skip to content

Instantly share code, notes, and snippets.

@nkohari
Created June 23, 2014 00:39
Show Gist options
  • Save nkohari/be5d1f62c25b6bd17787 to your computer and use it in GitHub Desktop.
Save nkohari/be5d1f62c25b6bd17787 to your computer and use it in GitHub Desktop.
Proof-of-concept of AngularJS-inspired dependency injection in React.js
Forge = require 'forge-di'
MonkeyPatcher = require './util/MonkeyPatcher'
Store = require './services/Store'
# Create the Forge and monkey-patch React.createClass() so it can inject dependencies.
forge = new Forge()
MonkeyPatcher.patchReact(forge)
# Register component bindings
forge.bind('store').to.type(Store)
React = require 'react'
_ = require 'underscore'
createClass = React.createClass
MonkeyPatcher = {}
MonkeyPatcher.patchReact = (forge) ->
return unless React.createClass is createClass
React.createClass = (dependencies..., spec) ->
if _.isFunction(spec)
args = _.map dependencies, (dep) ->
if dep.name is 'forge' then forge else forge.get(dep)
spec = spec.apply(spec, args)
createClass(spec)
module.exports = MonkeyPatcher
React = require 'react'
{div} = React.DOM
# If the last argument to React.createClass() is a function, the arguments will be resolved
# via Forge and passed to the function, allowing their use inside the component's functions.
Test = React.createClass 'store', (store) ->
getInitialState: ->
store.get(@props.id)
render: ->
(div {}, "Sup, my name is #{@state.name}")
module.exports = Test
@nkohari
Copy link
Author

nkohari commented Jun 23, 2014

I guess it depends on how militant you are about single responsibilities and loose coupling. For example, if you have components that receive new state via a web socket, you might want the "socket manager" piece to be injected via the closure rather than having it be a static dependency.

The way I've seen this typically solved is by putting state within the CommonJS module that's required, but that requires monkey-patching in order to test things, and can get unwieldy. In the end it's really a matter of choice, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment