<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { isEqual, differenceWith } from 'lodash'
import hoistStatics from 'hoist-non-react-statics'
import { watchEvents, unWatchEvents } from './actions/query'
import { getEventsFromInput, createCallable, wrapDisplayName } from './utils'
import ReactReduxFirebaseContext from './ReactReduxFirebaseContext'

// Reserved props that should not be passed into a firebaseConnect wrapped
// component. Will throw an error if they are.
const RESERVED_PROPS = ['_firebaseRef', '_dispatch']

/**
 * @name createFirebaseConnect
 * @description Function that creates a Higher Order Component that
 * automatically listens/unListens to provided firebase paths using
 * React's Lifecycle hooks.
 * **WARNING!!** This is an advanced feature, and should only be used when
 * needing to access a firebase instance created under a different store key.
 * @param {String} [storeKey='store'] - Name of redux store which contains
 * Firebase state (state.firebase)
 * @return {Function} - HOC that accepts a watchArray and wraps a component
 * @example <caption>Basic</caption>
 * // this.props.firebase set on App component as firebase object with helpers
 * import { createFirebaseConnect } from 'react-redux-firebase'
 * // create firebase connect that uses another redux store
 * const firebaseConnect = createFirebaseConnect('anotherStore')
 * // use the firebaseConnect to wrap a component
 * export default firebaseConnect()(SomeComponent)
 */
export const createFirebaseConnect = (storeKey = 'store') => (
  dataOrFn = []
) => WrappedComponent => {
  class FirebaseConnectWrapped extends Component {
    static displayName = wrapDisplayName(
      WrappedComponent,
      'FirebaseConnectWrapped'
    )
    static wrappedComponent = WrappedComponent

    firebaseEvents = []
    firebase = null
    prevData = null

    componentDidMount() {
      const { _firebaseRef, _dispatch } = this.props

      // Allow function to be passed
      const inputAsFunc = createCallable(dataOrFn)
      this.prevData = inputAsFunc(this.props, this.props)

      const { ref, helpers, storage, database, auth } = _firebaseRef
      this.firebase = { ref, storage, database, auth, ...helpers }

      this._firebaseEvents = getEventsFromInput(this.prevData)

      watchEvents(_firebaseRef, _dispatch, this._firebaseEvents)
    }

    componentWillUnmount() {
      const { _firebaseRef, _dispatch } = this.props
      unWatchEvents(_firebaseRef, _dispatch, this._firebaseEvents)
    }

    componentWillReceiveProps(np) {
      const { _firebaseRef, _dispatch } = this.props
      const inputAsFunc = createCallable(dataOrFn)
      const data = inputAsFunc(np, this.store)

      // Handle a data parameter having changed
      if (!isEqual(data, this.prevData)) {
        const itemsToSubscribe = differenceWith(data, this.prevData, isEqual)
        const itemsToUnsubscribe = differenceWith(this.prevData, data, isEqual)

        this.prevData = data
        // UnWatch all current events
        unWatchEvents(
          _firebaseRef,
          _dispatch,
          getEventsFromInput(itemsToUnsubscribe)
        )
        // Get watch events from new data
        this._firebaseEvents = getEventsFromInput(data)

        // Watch new events
        watchEvents(
          _firebaseRef,
          _dispatch,
          getEventsFromInput(itemsToSubscribe)
        )
      }
    }

    render() {
      // Prevent internal refs from being passed down to children
      let props = { ...this.props }
      delete props._firebaseRef
      delete props._dispatch
      return <WrappedComponent {...props} />
    }
  }

  FirebaseConnectWrapped.propTypes = {
    _dispatch: PropTypes.func.isRequired,
    _firebaseRef: PropTypes.object.isRequired
  }

  const HoistedComp = hoistStatics(FirebaseConnectWrapped, WrappedComponent)

  const FirebaseConnect = props => {<commit_msg>Made stripping of internal props based on the reserve props list<commit_after>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { isEqual, differenceWith } from 'lodash'
import hoistStatics from 'hoist-non-react-statics'
import { watchEvents, unWatchEvents } from './actions/query'
import { getEventsFromInput, createCallable, wrapDisplayName } from './utils'
import ReactReduxFirebaseContext from './ReactReduxFirebaseContext'

// Reserved props that should not be passed into a firebaseConnect wrapped
// component. Will throw an error if they are.
const RESERVED_PROPS = ['_firebaseRef', '_dispatch']

/**
 * @name createFirebaseConnect
 * @description Function that creates a Higher Order Component that
 * automatically listens/unListens to provided firebase paths using
 * React's Lifecycle hooks.
 * **WARNING!!** This is an advanced feature, and should only be used when
 * needing to access a firebase instance created under a different store key.
 * @param {String} [storeKey='store'] - Name of redux store which contains
 * Firebase state (state.firebase)
 * @return {Function} - HOC that accepts a watchArray and wraps a component
 * @example <caption>Basic</caption>
 * // this.props.firebase set on App component as firebase object with helpers
 * import { createFirebaseConnect } from 'react-redux-firebase'
 * // create firebase connect that uses another redux store
 * const firebaseConnect = createFirebaseConnect('anotherStore')
 * // use the firebaseConnect to wrap a component
 * export default firebaseConnect()(SomeComponent)
 */
export const createFirebaseConnect = (storeKey = 'store') => (
  dataOrFn = []
) => WrappedComponent => {
  class FirebaseConnectWrapped extends Component {
    static displayName = wrapDisplayName(
      WrappedComponent,
      'FirebaseConnectWrapped'
    )
    static wrappedComponent = WrappedComponent

    firebaseEvents = []
    firebase = null
    prevData = null

    componentDidMount() {
      const { _firebaseRef, _dispatch } = this.props

      // Allow function to be passed
      const inputAsFunc = createCallable(dataOrFn)
      this.prevData = inputAsFunc(this.props, this.props)

      const { ref, helpers, storage, database, auth } = _firebaseRef
      this.firebase = { ref, storage, database, auth, ...helpers }

      this._firebaseEvents = getEventsFromInput(this.prevData)

      watchEvents(_firebaseRef, _dispatch, this._firebaseEvents)
    }

    componentWillUnmount() {
      const { _firebaseRef, _dispatch } = this.props
      unWatchEvents(_firebaseRef, _dispatch, this._firebaseEvents)
    }

    componentWillReceiveProps(np) {
      const { _firebaseRef, _dispatch } = this.props
      const inputAsFunc = createCallable(dataOrFn)
      const data = inputAsFunc(np, this.store)

      // Handle a data parameter having changed
      if (!isEqual(data, this.prevData)) {
        const itemsToSubscribe = differenceWith(data, this.prevData, isEqual)
        const itemsToUnsubscribe = differenceWith(this.prevData, data, isEqual)

        this.prevData = data
        // UnWatch all current events
        unWatchEvents(
          _firebaseRef,
          _dispatch,
          getEventsFromInput(itemsToUnsubscribe)
        )
        // Get watch events from new data
        this._firebaseEvents = getEventsFromInput(data)

        // Watch new events
        watchEvents(
          _firebaseRef,
          _dispatch,
          getEventsFromInput(itemsToSubscribe)
        )
      }
    }

    render() {
      // Prevent reserved props from being passed down to children
      let props = Object.keys(this.props).reduce((acc, p) => {
        if (RESERVED_PROPS.indexOf(p) === -1) {
          acc[p] = this.props[p]
        }
        return acc
      }, {})

      return <WrappedComponent {...props} />
    }
  }

  FirebaseConnectWrapped.propTypes = {
    _dispatch: PropTypes.func.isRequired,
    _firebaseRef: PropTypes.object.isRequired
  }

  const HoistedComp = hoistStatics(FirebaseConnectWrapped, WrappedComponent)

  const FirebaseConnect = props => {
{'fraction_non_alphanumeric': 0.08673978065802593, 'fraction_numerical': 0.0001246261216350947, 'mean_word_length': 3.319160387513455, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4974445', 'n_tokens_mistral': 2205, 'n_tokens_neox': 2166, 'n_words': 644}