Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.update() needed even though the render function gets correct data? #1527

Closed
2 of 4 tasks
mikew opened this issue Feb 13, 2018 · 2 comments
Closed
2 of 4 tasks

.update() needed even though the render function gets correct data? #1527

mikew opened this issue Feb 13, 2018 · 2 comments

Comments

@mikew
Copy link

mikew commented Feb 13, 2018

Not sure if this is related to the bevy of other issues regarding .update needing to be called without any indication of why.

I noticed that this is happening with Redux as well, sometimes. It seems if the action is dispatched from a .simulate, all is well. But if you're just dispatching an action in code, you will need to call wrapper.update().

Where this breaks down for me is that we can spy on something in the render function and see that it gets the new updated value, so why doesn't the original wrapper instance work?

I've made a demo repo to check this out.

Current behavior

.update() needs to be called after Redux state changes, even though we can assert that the change happens correctly in the component's render function.

Expected behavior

.update() does not need to be called.

Your environment

API

  • shallow
  • mount
  • render

Version

library version
Enzyme 3.3.0
React 16.2.0

Adapter

  • enzyme-adapter-react-16
@mikew
Copy link
Author

mikew commented Feb 13, 2018

Maybe a more succicnt way of saying this would be:

Without calling .update(), we're left in some strange paradox where the value of this.props.foo is somehow different on lines 31 and 35.

@koba04
Copy link
Contributor

koba04 commented Feb 19, 2018

@mikew

This is an expected behavior in v3.

When you call mount() or shallow() Enzyme stores the result into ReactWrapper or ShallowWrapper.
After that, Enzyme uses the result for operations to the wrapper. (find(), text()...)

It means Enzyme have to sync the result between ReactWrapper and ReactDOMRenderer.
update() is an API for this.

In your case, dispatching Redux action means to update ReactElemenets owned by ReactDOMRenderer directly through instance.setState().
So Enzyme can't handle this to call update().

If you call simulate(), Enzyme can handle this like the following.

simulate(e) {
    this.simulateEvent(e);
    this.update(); 
}

So if you want to update ReactElements through a React Component instance directly, you have to call update() manually after the update.

   Enzyme                          React
|------------------|            |-------------------|
| ReactWrapper     | ---------- | ReactDOMRenderer  |
| ReactElements(A) |            | ReactElements(A)  |
| ---------------- |            |-------------------|

store.dispatch(action); // calling instance.setState() directly
// ReactWrapper can't recognize the update

// ReactWrapper still has ReactElements(A)
|------------------|            |-------------------|
| ReactWrapper     | ---------- | ReactDOMRenderer  |
| ReactElements(A) |            | ReactElements(B)  |
| ---------------- |            |-------------------|

// Updated react elements owned by ReactWrapper            
reactWrapper.update();

|------------------|            |-------------------|
| ReactWrapper     | <--------- | ReactDOMRenderer  |
| ReactElements(B) |     sync   | ReactElements(B)  |
| ---------------- |            |-------------------|

I think this should be fixed.
#1499 is a PR for this, which is for shallow but I can apply this mount as well.
But there are some unresolved issues, which are how to handle child wrappers etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants