4
votes

I am using learning about how to aframe with react and redux. I am creating custom components and registering them in my reactjs componentWillMount lifecycle event. For example: I am sending the result of my raycasting to the parent react component to be saved off for other purposes. This works great.

import React, {Component, PropTypes} from 'react'

export default class AframeComponent extends Component {
  static propTypes = {
    cb: PropTypes.func.isRequired
  }

  componentWillMount () {
    const {AFRAME} = window
    const aframeComponent = this

    if (!AFRAME) return

    if (!AFRAME.components['sphere-listener']) {
      AFRAME.registerComponent('sphere-listener', {
        init () {
          const {el} = this
          el.addEventListener('mouseup', (evt) => {
            const camera = document.querySelector('#camera')
            aframeComponent.handleRaycast(evt.detail.intersection.point, camera.components.rotation)
          })
        }
      })
    }
  }

  handleRaycast (position, rotation) {
    const {cb} = this.props

    /* do cool stuff here with the position and rotation */

    this.setState({position, rotation}, () => {
      cb(position, rotation)
    })
  }

  render () {
    return (
      <a-scene>
        <a-sphere radius="30" sphere-listener />
        <a-entity id="camera" look-controls mouse-cursor>
          <a-cursor fuse="true" color="yellow" />
        </a-entity>
        {/* cool stuff happens here */}
      </a-scene>
    )
  }
}

I'm encountering issues when I unmount the react component with aframe and remount it later in the app use. I'm getting errors but they make sense. The component I am registering an AFRAME is looking an object reference to a specific instance of AframeComponent that no longer exists the second time the component is loaded.

I have not found a way to officially unregister a component. I have been able to make it work but it feels hacky. In my component will unmount I can manually delete components then allow them to be re registered. delete AFRAME.components['sphere-listener']

Questions:

  1. Is there a way to AFRAME.unregisterComponent()?
  2. Am I just building components incorrectly as they have a state dependency? I'm beginning to think they should be stateless.
  3. If so how do I pass a function from a react class into the schema? Like this: <a-sphere radius="30" sphere-listener={cb: ${() => { console.log('call back') }}} />

Thanks,

Jordan

1

1 Answers

2
votes

Components should be registered at a global level, not at runtime. You should not be registering and unregistering components like you would DOM elements since there's not much benefit. But if you have to: delete AFRAME.components['sphere-listener']. EDIT: I do see you're trying to closure React variables into a component. Register/unregister kinda works, but I suggest decoupling them.

If you need to pass data into a component, you can use the schema, and bind data through the schema (e.g., somecomponent={{foo: this.state.blah}}).

You can't pass functions. You should use event listeners for communication <Entity events={{collide: () => {}}> and you can emit events at the A-Frame level.

Important to distinguish between what operations you should do within A-Frame components (3D, VR, events) and what operations you should do at the React level (view layer, data binding).