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

Shallow renderer "ReactWrapper::setState() expects a function as its second argument" when setState given a callback within the class #1769

Closed
rydash opened this issue Aug 18, 2018 · 2 comments

Comments

@rydash
Copy link

rydash commented Aug 18, 2018

Describe the bug
Shallow rendering components fails when setState(updater, callback) is called within componentDidMount and callback refers to a function within the current component class, accessed via this.

To reproduce

  1. Create a component like this:
import React from 'react';

class MyComponent extends React.Component {
  constructor() {
    super();
    this.state = {
      isLifecycle: false
    };
  }

  componentDidMount() {
    this.setState({ isLifecycle: true }, this.myCallback('Hello!'));
  }

  myCallback(message) {
    console.log(message);
  }

  render() {
    return <div></div>;
  }
}

export default MyComponent;
  1. Set up a test:
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from 'components/MyComponent';

describe('MyComponent', function() {
  it('renders', function() {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper).to.be.ok;
  });
});
  1. Run the test. (I did so using [email protected], [email protected], [email protected], and [email protected]. If other packages are relevant, I'm happy to describe them!)

  2. Receive the following error:

0 passing (22ms)
1 failing

  1) MyComponent
       renders:
     TypeError: ReactWrapper::setState() expects a function as its second argument
      at ShallowWrapper.setState (node_modules/enzyme/build/ShallowWrapper.js:508:17)
      at MyComponent.ShallowWrapper.instance.setState (node_modules/enzyme/build/ShallowWrapper.js:190:35)
      at MyComponent.componentDidMount (src/js/components/MyComponent.js:12:10)
      at /Users/ryanmcgill/repos/fake/node_modules/enzyme/build/ShallowWrapper.js:196:22
      at Object.batchedUpdates (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:392:22)
      at new ShallowWrapper (node_modules/enzyme/build/ShallowWrapper.js:195:26)
      at shallow (node_modules/enzyme/build/shallow.js:21:10)
      at Context.<anonymous> (test/components/MyComponent.spec.js:7:21)

Expected behavior
The callback is called with the provided message, and the test succeeds.

Desktop:

Additional context
This was behaving as expected in [email protected].

I am not currently sure which area of the code is causing Enzyme to transform this parameter or otherwise not identify it as a function.

Interestingly, each of the following callback styles will work with [email protected]:

  componentDidMount() {
    this.setState({ isLifecycle: true }, () => console.log('Whazzup'));
  }

or

  componentDidMount() {
    this.setState({ isLifecycle: true }, () => this.myCallback('Howdy!'));
  }

Of course, converting such callbacks to use fat arrow functions may not be feasible or introduce bugs for full applications.

@ljharb
Copy link
Member

ljharb commented Aug 18, 2018

That's because in the latter case, it's an actual function - in this.setState({ isLifecycle: true }, this.myCallback('Hello!')); you're not actually passing a callback, you're passing the return value of this.myCallback.

In other words, your code is incorrect, and you need to pass an actual function there.

@ljharb ljharb closed this as completed Aug 18, 2018
@rydash
Copy link
Author

rydash commented Aug 18, 2018

Whoops, looks like I should've applied my brain a little harder! Sorry for that - it is interesting that this case went uncaught by [email protected] or even React. It also appears everything works if the return value of this.myCallback() is itself a function, so that's good.

Thank you for the explanation; I'll go fix my stuff!

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

No branches or pull requests

2 participants