Repository URL to install this package:
|
Version:
1.1.16 ▾
|
/**
* @file this file is for connecting a component to data with 2 functions
* @see ./connectToData for the extensive usage by containers
*/
import React from 'react'
import { isObj } from 'exotic'
import { observer, inject } from 'xmobx/mobx-react'
// @todo THIS SHOULD NOT BE DONE
import { withJob } from 'modules/SSR/react-jobs'
// @TODO note about https://jira.skava.net/confluence/display/ux/forking+modules+and+creating+our+own
// in this case for example, we need to get the display name from many places
// - from styles view,
// - to types wrapping,
// - to other data connecting factories or containers
// - to debug tools
// - to replacing the one in the modules we've forked like react-jobs for example
// this function we use gets names from more than just react, very reusable
// here, we pull an external one, and deoptimize our internal one
// import wrapDisplayName from 'recompose/wrapDisplayName'
import { toComponentName } from 'modules/identifier'
import { isUniqueRouteChange } from 'modules/router'
import { omniContainer } from './oneState'
import { tapProps } from './deps'
// @TODO
// import { ContainerBase } from 'modules/chain-able/container-builder'
// class OneConnect extends ContainerBase {}
// -------------------- ONE CONNECT FACTORY ------------
// declare class ProvidedInjectedReactComponent extends Provider, Inject, React.Component { }
// declare function handleStoreAndDataFromApi(store: typeof OmniStoreType, dataFromApi: Serializable): any
// declare function fetchApiDataFunction(routerEntries: typeof RouterEntries): Promise<Serializable>
// @TODO need to pass in unique sometime with chain extension
// if (arguments.length)
function dataFactory(dataToStoreHandler, functionToCallApis, handleProps = tapProps) {
const addServerSideRendering = withJob({
work: functionToCallApis,
shouldWorkAgain: isUniqueRouteChange,
})
/**
* @param {React.Component} Target component to decorate
* @return {React.Component} decorated & injected & observer
*/
return function(Target) {
// @NOTE IMPORTANT, MUST MAKE TARGET COMPONENT ITSELF AN OBSERVER
const ViewComponent = observer(Target)
// annoying we still need this <<< remove this, is only used in state/user
// @inject('store')
@observer
class Decorated extends React.Component {
componentWillMount() {
const { store, omniStore, jobResult } = handleProps(this.props, false)
return dataToStoreHandler(store, jobResult)
}
componentWillReceiveProps(nextProps) {
if (nextProps.jobResult.identifier !== this.props.jobResult.identifier) {
const store = this.props.store || omniContainer.store
console.dev('Reacted with componentWillRecieveProps')
return dataToStoreHandler(store, nextProps.jobResult)
}
return false
}
componentWillReact() {
const { store, jobResult } = handleProps(this.props, false)
console.dev('Reacted with componentWillReact')
return dataToStoreHandler(store, jobResult)
}
render() {
return <ViewComponent {...handleProps(this.props)} />
}
}
// @TODO take this back out again
// Decorated.prototype.componentWillReceiveProps = componentWillReceiveProps
// @see examples/end-to-end state example
// Decorated.displayName = wrapDisplayName(Target, 'OneConnect')
Decorated.displayName = '1Connect(' + toComponentName(Target) + ')'
Decorated.originalWrappedComponent = Target
return addServerSideRendering(Decorated)
}
}
export { dataFactory }
export default dataFactory