Enzyme: `.update()` method does not update `props` cache of child wrappers

Created on 3 Nov 2017  路  4Comments  路  Source: enzymejs/enzyme

Problem

The prop or props methods return stale values, even after update is called on the root wrapper.

Expected behaviour

Either the wrapper.update() function should invalidate the props of all wrappers that derive from it, or else .props() should always fetch the props from the adapter, and not rely on a cached version.

See failing test in this PR: https://github.com/airbnb/enzyme/pull/1322.

v3 expected difference

Most helpful comment

This is expected behavior in v3; wrappers are immutable.

As for props, are we talking about shallow or mount? A shallow wrapper is what the component renders - so its .props() might update - but a mount wrapper is the component itself - so its .props() will never change, until you use setProps().

All 4 comments

I just encountered this, and had to do

wrapper.find('ChildComponent').somethingThatChangesStuff()
wrapper.update()
wrapper.find('ChildComponent').props()

-- which is obnoxious

This is expected behavior in v3; wrappers are immutable.

As for props, are we talking about shallow or mount? A shallow wrapper is what the component renders - so its .props() might update - but a mount wrapper is the component itself - so its .props() will never change, until you use setProps().

I'd like to keep this conversation flowing. I think it's stalled due to confusion. I'm going to do my best to move it forward.

This is expected behavior in v3; wrappers are immutable.

Immutable is an interesting term to use. I might be misunderstanding how it's being applied here. If I do:

console.log(wrapper.props());
setTimeout(() => {
  wrapper.update();
  console.log(wrapper.props()); 
}, 1000);

And the two logs could result in different values (because there's a timer that's changing stuff inside the component), then is wrapper really immutable? Anyway, maybe we're talking semantics, but if the above is true, then I think what we're saying (though I may be only speaking for myself) is that we would expect this to also be true:

const child = wrapper.find('ChildComponent')
console.log(child.props());
setTimeout(() => {
  wrapper.update()
  console.log(child.props());
}, 1000);

If something happens within the component within the one second lapse in time, and a prop is changed on the ChildComponent, then we would expect the second console.log() to reflect the child's updated properties. In other words, we expect wrapper.update() to not only update wrapper but also any wrappers that were derived from that wrapper through prior selections.

I suspect the answer is still "this is expected behavior", but hopefully this helps clear some confusion?

@Aaronius fair; it's more that wrappers do not automatically update, and specifically, derived wrappers are entirely cut off from the wrapper they originate from.

In practice, this means that you'll always need to re-find from the root, and call .update() on the root, to get an updated wrapper.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aweary picture aweary  路  3Comments

ahuth picture ahuth  路  3Comments

thurt picture thurt  路  3Comments

abe903 picture abe903  路  3Comments

blainekasten picture blainekasten  路  3Comments