`useEffect` not called when the component is `shallow` renderered
See original GitHub issueCurrent behavior
useEffect
fonction does not seem to be executed when the component is rendered with shallow
.
Given the following simple component using useEffect
hook to call a method given as a prop:
import React, { useEffect } from 'react';
export const MyComponent = ({ callback }) => {
useEffect(() => {
callback('Say something');
});
return <div>Hello world!</div>;
};
And the following tests checking that the callback
function is indeed called accordingly:
import React from 'react';
import { shallow, mount } from 'enzyme';
import { MyComponent } from '../MyComponent';
describe('MyComponent', () => {
describe('shallow render', () => {
it('should call callback when shallow rendered', () => {
const callback = jest.fn();
shallow(<MyComponent callback={callback} />);
expect(callback).toHaveBeenCalled();
});
});
describe('mount', () => {
it('should call callback when mounted', () => {
const callback = jest.fn();
mount(<MyComponent callback={callback} />);
expect(callback).toHaveBeenCalled();
});
});
});
We observe that the method is called as expected when “mounted”, but not when using a shallow
renderer:
FAIL src/tests/MyComponent.test.js
MyComponent
shallow render
✕ should call callback when shallow rendered (12ms)
mount
✓ should call callback when mounted (24ms)
● MyComponent › shallow render › should call callback when shallow rendered
expect(jest.fn()).toHaveBeenCalled()
Expected mock function to have been called, but it was not called.
8 | const callback = jest.fn();
9 | shallow(<MyComponent callback={callback} />);
> 10 | expect(callback).toHaveBeenCalled();
| ^
11 | });
12 | });
13 |
at Object.toHaveBeenCalled (src/tests/MyComponent.test.js:10:24)
You may find this reproducible example here.
Expected behavior
When using shallow
to render the components, the function passed to useEffect
should be executed, as it is when using mount
.
Your environment
API
- shallow
- mount
- render
Version
library | version |
---|---|
enzyme | 3.9.0 |
react | 16.8.6 |
react-dom | 16.8.6 |
react-test-renderer | 16.8.6 |
adapter (below) |
Adapter
- enzyme-adapter-react-16
- enzyme-adapter-react-16.3
- enzyme-adapter-react-16.2
- enzyme-adapter-react-16.1
- enzyme-adapter-react-15
- enzyme-adapter-react-15.4
- enzyme-adapter-react-14
- enzyme-adapter-react-13
- enzyme-adapter-react-helper
- others ( )
Issue Analytics
- State:
- Created 4 years ago
- Reactions:301
- Comments:68 (13 by maintainers)
Top Results From Across the Web
Testing a component that uses useEffect using Enzyme ...
I've solved / worked around this by: not using shallow rendering from Enzyme anymore; use the React Testing Library instead of Enzyme; mocking ......
Read more >Shallow Renderer - React
Shallow rendering lets you render a component “one level deep” and assert facts about what its render method returns, without worrying about the...
Read more >Shallow rendering & React Hooks. And why shallow rendering ...
They simply don't know that a component calls useEffect() . Yet, it's being called when you invoke shallow() .
Read more >Testing useEffect and Redux Hooks using Enzyme - Medium
Enzyme doesn't support effect hooks by default while shallow mounting components. You'd need to add jest-react-hooks-shallow to ensure that the ...
Read more >Shallow Testing Hooks with Enzyme - Carbon Five Blog
The trick to shallow testing hooks like useEffect is to use spies. The examples here are specifically for Jest, but they should work...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Please stop posting solutions/issues that relate to
mount()
. This issue relates to limitations ofshallow()
when trying to confirm expected changes made byuseEffect
when usingsetProps
orupdate()
. There are already ample solutions that show howmount()
can be used. This is also not the place to discuss the pros and cons of shallow/deep rendering. Thanks!Seriously guys, just use
mount()
instead ofshallow()
. Changes are minimal, and you can still mock sub-components to stop full tree-loading. As an example of how easy the switch is, I had code as follows:that was changed to the following when a class component was converted to a functional component, and logic from lifecycle events (e.g.
componentDidUpdate
) was moved to useEffect: