 module.exports = React.createClass
   displayName: 'PromiseRenderer'
 
-  pendingClass: 'promise-pending'
-
-  propTypes:
-    promise: React.PropTypes.instanceOf(Promise).isRequired
-    then: React.PropTypes.func.isRequired
-    catch: React.PropTypes.func
-
   getDefaultProps: ->
+    promise: Promise.reject()
+    pendingClass: 'promise-pending'
+    tag: 'span'
+    then: @::defaultThen
     catch: @::defaultCatch
 
   getInitialState: ->

        error: null

    promise.catch (error) =>
      @safelySetState
        pending: false
        resolved: false
        rejected: true
        value: null
        error: error

  safelySetState: (state) ->
    if @isMounted()
      @setState state

  render: ->
    if @state.resolved
      try
        @props.then.call this, @state.value
      catch e
        @props.catch.call this, e

    else if @state.rejected
      @props.catch.call this, @state.error

    else
      # Until the initial promise is resolved or rejected, show the given children.

  componentDidUpdate: (prevProps, prevState) ->
    classList = @getDOMNode()?.classList
    if @state.pending
      classList?.add @props.pendingClass
    else
      classList?.remove @props.pendingClass

  renderResolved: (value) ->
    if typeof @props.then is 'string'
      @renderSimpleLookup value, @props.then.split '.'
    else
      @props.then.call this, value

  renderSimpleLookup: (value, path) ->
    until path.length is 0
      value = value[path.shift()]
    React.createElement @props.tag, @props, value

  renderRejected: (error) ->
    @props.catch.call this, error

  defaultThen: (value) ->
    React.createElement @props.tag, @props, value

  defaultCatch: (error) ->
    React.createElement @props.tag, @props, <code>{error.toString()}</code>
