Skip to content
This repository has been archived by the owner on Dec 31, 2020. It is now read-only.

TypeScript, MobX-React, and RefObjects #619

Closed
wants to merge 10 commits into from
83 changes: 53 additions & 30 deletions src/inject.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, createElement } from "react"
import React, { Component, createElement } from "react"
import hoistStatics from "hoist-non-react-statics"
import * as PropTypes from "./propTypes"
import { observer } from "./observer"
Expand Down Expand Up @@ -33,22 +33,9 @@ const proxiedInjectorProps = {
/**
* Store Injection
*/
function createStoreInjector(grabStoresFn, component, injectNames) {
let displayName =
"inject-" +
(component.displayName ||
component.name ||
(component.constructor && component.constructor.name) ||
"Unknown")
if (injectNames) displayName += "-with-" + injectNames
function createStoreInjector(grabStoresFn, component, forwardedRef) {

class Injector extends Component {
static displayName = displayName

storeRef = instance => {
this.wrappedInstance = instance
}

render() {
// Optimization: it might be more efficient to apply the mapper function *outside* the render method
// (if the mapper is a function), that could avoid expensive(?) re-rendering of the injector component
Expand All @@ -65,17 +52,13 @@ function createStoreInjector(grabStoresFn, component, injectNames) {
}

if (!isStateless(component)) {
newProps.ref = this.storeRef
newProps.ref = forwardedRef;
}

return createElement(component, newProps)
}
}

// Static fields from component should be visible on the generated Injector
hoistStatics(Injector, component)

Injector.wrappedComponent = component
Object.defineProperties(Injector, proxiedInjectorProps)

return Injector
Expand Down Expand Up @@ -110,21 +93,61 @@ export default function inject(/* fn(stores, nextProps) or ...storeNames */) {
let grabStoresFn
if (typeof arguments[0] === "function") {
grabStoresFn = arguments[0]
return function(componentClass) {
let injected = createStoreInjector(grabStoresFn, componentClass)
injected.isMobxInjector = false // supress warning
// mark the Injector as observer, to make it react to expressions in `grabStoresFn`,
// see #111
injected = observer(injected)
injected.isMobxInjector = true // restore warning
return injected
return function(component) {
let displayName =
"inject-" +
(component.displayName ||
component.name ||
(component.constructor && component.constructor.name) ||
"Unknown")

let forwardRef = React.forwardRef((props, ref) => {
let injected = createStoreInjector(grabStoresFn, component, ref)
injected.isMobxInjector = false // supress warning
// mark the Injector as observer, to make it react to expressions in `grabStoresFn`,
// see #111
injected = observer(injected)
injected.isMobxInjector = true // restore warning

return createElement(injected, props)
})

// Static fields from component should be visible on the generated Injector
hoistStatics(forwardRef, component)
forwardRef.wrappedComponent = component
Object.defineProperties(forwardRef, proxiedInjectorProps)
forwardRef.displayName = displayName;

return forwardRef
}
} else {
const storeNames = []
for (let i = 0; i < arguments.length; i++) storeNames[i] = arguments[i]
grabStoresFn = grabStoresByName(storeNames)
return function(componentClass) {
return createStoreInjector(grabStoresFn, componentClass, storeNames.join("-"))
return function(component) {
let displayName =
"inject-" +
(component.displayName ||
component.name ||
(component.constructor && component.constructor.name) ||
"Unknown") +
"-with-" +
storeNames.join("-")


let forwardRef = React.forwardRef((props, ref) => {
return createElement(
createStoreInjector(grabStoresFn, component, ref),
props)
})

// Static fields from component should be visible on the generated Injector
hoistStatics(forwardRef, component)
forwardRef.wrappedComponent = component
Object.defineProperties(forwardRef, proxiedInjectorProps)
forwardRef.displayName = displayName;

return forwardRef
}
}
}
4 changes: 1 addition & 3 deletions test/inject.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,7 @@ describe("inject based context", () => {
expect(C.bla2 === B.bla2).toBeTruthy()
expect(Object.keys(C.wrappedComponent.propTypes)).toEqual(["x"])

const wrapper = mount(<C booh={42} />)
await sleepHelper(10)
expect(wrapper.instance().wrappedInstance.testField).toBe(1)
mount(<div><C ref={ref => expect(ref.testField).toBe(1)} booh={42} /></div>)
})

test("warning is printed when attaching contextTypes to HOC", () => {
Expand Down