diff --git a/packages/nerv-redux/__tests__/provider.spec.js b/packages/nerv-redux/__tests__/provider.spec.js index 6f2b6bf2..6550b396 100644 --- a/packages/nerv-redux/__tests__/provider.spec.js +++ b/packages/nerv-redux/__tests__/provider.spec.js @@ -53,14 +53,25 @@ describe('nerv-redux', () => { // ) }) - it('store should be in the context', () => { + it('should have store in the context', () => { const store = createStore(() => ({})) + let child + const getRef = (ref) => { + child = ref + } + class ProviderChild extends Component { + render () { return null } + } const instance = renderToContainer( - + ) - expect(instance.context.store).toEqual(store) + + expect(child.context.store).toEqual(store) + + // shouldn't modify Provider.context + expect(instance.context).toEqual({}) }) it('should pass state consistently to mapState', async () => { diff --git a/packages/nerv-utils/src/index.ts b/packages/nerv-utils/src/index.ts index 216792d8..2e2f52d0 100644 --- a/packages/nerv-utils/src/index.ts +++ b/packages/nerv-utils/src/index.ts @@ -19,17 +19,31 @@ export function isAttrAnEvent (attr: string): boolean { return attr[0] === 'o' && attr[1] === 'n' } -export function extend (source: S, from: F): S | F & S { - if (!from) { - return source - } - for (const key in from) { - if (from.hasOwnProperty(key)) { - (source as any)[key] = from[key] +const extend = ((): ((source: S, from: F) => S | F & S) => { + if ('assign' in Object) { + return (source: S, from: F): S | F & S => { + if (!from) { + return source + } + Object.assign(source, from) + return source + } + } else { + return (source: S, from: F): S | F & S => { + if (!from) { + return source + } + for (const key in from) { + if (from.hasOwnProperty(key)) { + (source as any)[key] = from[key] + } + } + return source } } - return source -} +})() + +export { extend } export function clone (obj: T): T | {} { return extend({}, obj) diff --git a/packages/nerv/src/dom.ts b/packages/nerv/src/dom.ts index f92acbc9..e6f15842 100644 --- a/packages/nerv/src/dom.ts +++ b/packages/nerv/src/dom.ts @@ -1,5 +1,6 @@ import { isValidElement as isValidNervElement, VType, isComponent, isInvalid } from 'nerv-shared' import { nextTick } from 'nerv-utils' +import { getChildContext } from './lifecycle' import { render } from './render' import { unmount } from './vdom/unmount' import createElement from './create-element' @@ -49,7 +50,7 @@ export function unstable_renderSubtreeIntoContainer ( // @TODO: should handle props.context? const wrapper = createElement( WrapperComponent, - { context: parentComponent.context }, + { context: getChildContext(parentComponent, parentComponent.context) }, vnode ) const rendered = render(wrapper as any, container) diff --git a/packages/nerv/src/full-component.ts b/packages/nerv/src/full-component.ts index 9a78ae7b..f3d1f6ad 100644 --- a/packages/nerv/src/full-component.ts +++ b/packages/nerv/src/full-component.ts @@ -37,6 +37,7 @@ class ComponentWrapper implements CompositeComponent { } update (previous, current, parentContext, domNode?) { + this.context = parentContext return reRenderComponent(previous, this) } diff --git a/packages/nerv/src/lifecycle.ts b/packages/nerv/src/lifecycle.ts index 5125b867..0f962636 100644 --- a/packages/nerv/src/lifecycle.ts +++ b/packages/nerv/src/lifecycle.ts @@ -1,4 +1,5 @@ -import { extend, isFunction, isNumber, isString } from 'nerv-utils' +// import { extend, isFunction, isNumber, isString } from 'nerv-utils' +import { extend, isFunction, isNumber, isString, clone } from 'nerv-utils' import CurrentOwner from './current-owner' import createElement from './vdom/create-element' import createVText from './vdom/create-vtext' @@ -13,7 +14,8 @@ import { VText, VVoid, VNode, - VType + VType, + EMPTY_OBJ } from 'nerv-shared' import FullComponent from './full-component' import Stateless from './stateless-component' @@ -111,11 +113,11 @@ export function mountStatelessComponent (vnode: Stateless, parentContext) { return (vnode.dom = mountVNode(vnode._rendered, parentContext) as Element) } -export function getChildContext (component, context) { +export function getChildContext (component, context = EMPTY_OBJ) { if (component.getChildContext) { - return extend(context, component.getChildContext()) + return extend(clone(context), component.getChildContext()) } - return context + return clone(context) } export function renderComponent (component: Component) { @@ -153,7 +155,7 @@ export function reRenderComponent ( ) { const component = (current.component = prev.component) const nextProps = current.props - const nextContext = component.context + const nextContext = current.context component._disable = true if (isFunction(component.componentWillReceiveProps)) { errorCatcher(() => {