Skip to content

Commit

Permalink
fix(nerv): fix the buggy behavior of modifying context when calling g…
Browse files Browse the repository at this point in the history
…etChildContext
  • Loading branch information
Littly committed Jul 13, 2018
1 parent 5259771 commit 56911c6
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 19 deletions.
17 changes: 14 additions & 3 deletions packages/nerv-redux/__tests__/provider.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(
<Provider store={store}>
<Child />
<ProviderChild ref={getRef} />
</Provider>
)
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 () => {
Expand Down
32 changes: 23 additions & 9 deletions packages/nerv-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,31 @@ export function isAttrAnEvent (attr: string): boolean {
return attr[0] === 'o' && attr[1] === 'n'
}

export function extend<S, F> (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 = ((): (<S, F>(source: S, from: F) => S | F & S) => {
if ('assign' in Object) {
return <S, F>(source: S, from: F): S | F & S => {
if (!from) {
return source
}
Object.assign(source, from)
return source
}
} else {
return <S, F>(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<T> (obj: T): T | {} {
return extend({}, obj)
Expand Down
3 changes: 2 additions & 1 deletion packages/nerv/src/dom.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions packages/nerv/src/full-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ComponentWrapper implements CompositeComponent {
}

update (previous, current, parentContext, domNode?) {
this.context = parentContext
return reRenderComponent(previous, this)
}

Expand Down
14 changes: 8 additions & 6 deletions packages/nerv/src/lifecycle.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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'
Expand Down Expand Up @@ -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<any, any>) {
Expand Down Expand Up @@ -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(() => {
Expand Down

0 comments on commit 56911c6

Please sign in to comment.