Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syntax error after upgrade to 3.0.8 ? #42

Closed
crapthings opened this issue Jan 16, 2018 · 2 comments
Closed

syntax error after upgrade to 3.0.8 ? #42

crapthings opened this issue Jan 16, 2018 · 2 comments

Comments

@crapthings
Copy link

this is a WIP package code

see screenshot

image

import React, { Component } from 'react'
import { render } from 'react-dom'

const config = {
  loading: <div>loading</div>,

  fault: <div>fault</div>,

  error: error => <div>
    {JSON.stringify(error)}
  </div>,
}

const { loading } = config

// React Error Boundary
class WithFault extends Component {
  state = {
    fault: false,
  }

  componentDidCatch(error, info) {
    this.setState({ fault: true, error, info })
  }

  render() {
    const { fault, error, info } = this.state

    if (!fault)
      return this.props.children

    return config.fault
  }
}

// Meteor.subscribe wrapper
class WithSubscribe extends Component {
  state = {
    ready: false,
    stop: false,
    error: undefined,
  }

  componentDidMount() {
    this.subscribe()
  }

  componentWillUnmount() {
    this.unsubscribe()
  }

  render() {
    const { ready, stop, error } = this.state
    const { children, loading } = this.props
    if (error)
      return config.error(error)

    if (stop)
      return null

    if (!ready)
      return loading || config.loading

    const props = {
      _subscribeHandler: this.subscribeHandler,
      _subscriptionId: this.subscribeHandler.subscriptionId,
    }

    return children.$$typeof
      ? children
      : children(props)
  }

  getSubscriptionArgs = () => {
    const args = getArgs(this.props)
    const callbackObj = args.slice(-1)
    if (!callbackObj.onStop)
      args.push({ onStop: this.onStop })
    return args
  }

  subscribe = () => {
    const subscriptionArgs = this.getSubscriptionArgs()
    this.trackerHandler = Meteor.autorun(computation => {
      this.subscribeHandler = Meteor.subscribe.apply(Meteor.subscribe, subscriptionArgs)
      const ready = this.subscribeHandler.ready()
      this.setState({ ready })
    })
  }

  unsubscribe = () => {
    if (this.trackerHandler)
      this.trackerHandler.stop()
    if (this.subscribeHandler)
      this.subscribeHandler.stop()
  }

  onStop = error => {
    if (error)
      return this.setState({ error })

    this.setState({ stop: true })
  }
}

// Meteor.autorun wrapper
class WithTracker extends Component {
  state = {
    error: undefined,
    data: {
      list: [],
      item: undefined,
    },
  }

  _data = {}

  componentWillMount() {
    this.resolve()
  }

  componentWillUnmount() {
    if (this.trackerHandler)
      this.trackerHandler.stop()
  }

  render() {
    const { props, state } = this
    const { children } = props
    const { data } = state
    return children({ data })
  }

  resolve = () => {
    const { list, item, data } = this.props

    if (list)
      return this.resolveList()

    if (item)
      return this.resolveItem()

    this.resolveData()
  }

  resolveData = () => {
    const { list, item, data } = this.props
    this.trackerHandler = Meteor.autorun(computation => {
      for (const key in data) {
        const value = this.resolveValue(data[key])
        this.setData(key, value)
      }
      this.setState({ data: this.getData() })
    })
  }

  resolveList = () => {
    const { list } = this.props
    this.trackerHandler = Tracker.autorun(computation => {
      const value = this.resolveValue(list)
      this.setState({ data: { list: value } })
    })
  }

  resolveItem = () => {
    const { item } = this.props
    this.trackerHandler = Meteor.autorun(computation => {
      const value = this.resolveValue(item)
      this.setState({ data: { item: value } })
    })
  }

  resolveValue = value => {
    if (isFunction(value))
      value = value(this)

    if (value instanceof Mongo.Cursor)
      value = value.fetch()

    return value
  }

  getData = key => {
    if (key)
      return this._data[key]

    return this._data
  }

  setData = (key, value) => {
    this._data[key] = value
  }
}

// Meteor.call wrapper
class WithCall extends Component {
  state = {
    ready: false,
    error: undefined,
    data: undefined,
  }

  componentWillMount() {
    this.resolveCall()
  }

  render() {
    const { ready, error, data } = this.state
    const { children, loading } = this.props

    if (!ready)
      return loading || config.loading

    return (
      children({ data })
    )
  }

  getCallArgs = () => getArgs(this.props)

  resolveCall = () => {
    const callArgs = this.getCallArgs()
    const [callback] = callArgs.slice(-1)

    if (!isFunction(callback))
      callArgs.push(this.callback)

    Meteor.call.apply(Meteor.call, callArgs)
  }

  callback = (error, data) => {
    const ready = true
    error
      ? this.setState({ ready, error })
      : this.setState({ ready, data })
  }
}

// without Meteor.userId wrapper
class WithUserId extends Component {
  state = {
    ready: false,
    userId: null,
  }

  componentWillMount() {
    this.resolveUserId()
  }

  componentWillUnmount() {
    if (this.trackerHandler)
      this.trackerHandler.stop()
  }

  render() {
    const { ready, userId } = this.state
    const { children, loading } = this.props

    if (!userId)
      return null

    if (userId && !ready)
      return loading || config.loading

    return children
  }

  resolveUserId() {
    this.trackerHandler = Meteor.autorun(computation => {
      const userId = Meteor.userId()
      const ready = !Meteor.loggingIn()
      this.setState({ userId, ready })
    })
  }
}

// without Meteor.userId wrapper
class WithoutUserId extends Component {
  state = {
    userId: null,
  }

  componentWillMount() {
    this.resolveUserId()
  }

  componentWillUnmount() {
    if (this.trackerHandler)
      this.trackerHandler.stop()
  }

  render() {
    const { userId } = this.state
    const { children } = this.props

    if (userId)
      return null

    return children
  }

  resolveUserId() {
    this.trackerHandler = Meteor.autorun(computation => {
      const userId = Meteor.userId()
      this.setState({ userId })
    })
  }
}

// Meteor.user() wrapper
class WithUser extends Component {
  state = {
    user: undefined,
  }

  componentWillMount() {
    this.resolveUser()
  }

  componentWillUnmount() {
    if (this.trackerHandler)
      this.trackerHandler.stop()
  }

  render() {
    const { user } = this.state
    const { children } = this.props

    if (!children || children && children.$$typeof)
      throw new Error('WithUser\'s children should be a function that return component')

    if (!user)
      return null

    return children(user)
  }

  resolveUser() {
    this.trackerHandler = Meteor.autorun(computation => {
      const user = Meteor.user()
      this.setState({ user })
    })
  }
}

function Mount(component, options = {}) {
  const defaultOptions = {
    id: 'react-root',
    withFault: true,
  }

  options = Object.assign({}, defaultOptions, options)

  Meteor.startup(function () {
    const div = document.createElement('div')
    div.id = options.id
    document.body.appendChild(div)


    if (options.withFault)
      return render(<WithFault>
        {component}
      </WithFault>, div)

    render(component, div)
  })
}

// utils

function getArgs(props) {
  const { name, args } = props

  if (!name && !isString(name))
    throw new Error('name must be specified')

  if (!args)
    return [name]

  if (!Array.isArray(args))
    return [name, args]

  return [name].concat(args)
}

function isString(target) {
  return isType(target, 'String')
}

function isFunction(target) {
  return isType(target, 'Function')
}

function isType(target, type) {
  return Object.prototype.toString.call(target) === `[object ${type}]` ? true : false
}

module.exports = {
  WithFault,
  WithSubscribe,
  WithTracker,
  WithCall,
  WithUserId,
  WithoutUserId,
  WithUser,
  Mount,
  config,
}
@borela
Copy link
Owner

borela commented Jan 16, 2018

I sent a commit that fix this 25f4ba6, the Object global was holding on to the context.

@borela
Copy link
Owner

borela commented Jan 17, 2018

@borela borela closed this as completed Jan 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants