Skip to content

Commit

Permalink
Adds support for UNSAFE_componentWillMount and getDerivedStateFromProps.
Browse files Browse the repository at this point in the history
  • Loading branch information
ctrlplusb committed Jul 10, 2018
1 parent 3c8890e commit 2e43996
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 3 deletions.
54 changes: 54 additions & 0 deletions src/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,60 @@ describe('reactTreeWalker', () => {
)
})

it('UNSAFE_componentWillMount', () => {
let actual = {}

class Foo extends Component {
constructor(props) {
super(props)
this.state = { foo: 'foo' }
}

UNSAFE_componentWillMount() {
this.setState({ foo: 'bar' })
}

render() {
actual = this.state
return h('div', null, this.state.foo)
}
}

return reactTreeWalker(h(Foo, { value: 'foo' }), () => true).then(
() => {
const expected = { foo: 'bar' }
expect(actual).toMatchObject(expected)
},
)
})

it('getDerivedStateFromProps', () => {
let actual = {}

class Foo extends Component {
constructor(props) {
super(props)
this.state = { foo: 'foo' }
}

static getDerivedStateFromProps(props, state) {
return { foo: `${state.foo}bar` }
}

render() {
actual = this.state
return h('div', null, this.state.foo)
}
}

return reactTreeWalker(h(Foo, { value: 'foo' }), () => true).then(
() => {
const expected = { foo: 'foobar' }
expect(actual).toMatchObject(expected)
},
)
})

it('calls componentWillUnmount', () => {
let called = true

Expand Down
20 changes: 17 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ const ensureChild = child =>
const getChildren = element =>
element.props && element.props.children
? element.props.children
: element.children ? element.children : undefined
: element.children
? element.children
: undefined

// Preact uses "nodeName", React uses "type"
const getType = element => element.type || element.nodeName
Expand Down Expand Up @@ -192,7 +194,9 @@ export default function reactTreeWalker(
const instance = new Component(props, currentContext)

// In case the user doesn't pass these to super in the constructor
instance.props = instance.props || props
Object.defineProperty(instance, 'props', {
value: instance.props || props,
})
instance.context = instance.context || currentContext
// set the instance state to null (not undefined) if not set, to match React behaviour
instance.state = instance.state || null
Expand All @@ -210,7 +214,17 @@ export default function reactTreeWalker(
instance.state = Object.assign({}, instance.state, newState)
}

if (instance.componentWillMount) {
if (Component.getDerivedStateFromProps) {
const result = Component.getDerivedStateFromProps(
instance.props,
instance.state,
)
if (result !== null) {
instance.state = Object.assign({}, instance.state, result)
}
} else if (instance.UNSAFE_componentWillMount) {
instance.UNSAFE_componentWillMount()
} else if (instance.componentWillMount) {
instance.componentWillMount()
}

Expand Down

0 comments on commit 2e43996

Please sign in to comment.