title: setup function returns undefined when testing a custom hook usePrevious
body: <p>I have got code for usePrevious hook from somewhere on internet. The code for usePrevious looks like:</p>
  
  <pre class="lang-js prettyprint-override"><code>export const usePrevious = (value) =&gt; {
    const ref = useRef();
    useEffect(() =&gt; {
      ref.current = value;
    }, [value]);
    return ref.current;
  };
  </code></pre>
  
  <p>Now, I am learing testing react with jest and enzyme. So, I tried to test usePrevious and got some problems. Here is my test case:</p>
  
  <pre class="lang-js prettyprint-override"><code>import React from 'react';
  import { render } from 'enzyme';
  
  import { usePrevious } from './customHooks';
  
  const Component = ({ children, value }) =&gt; children(usePrevious(value));
  const setup = (value) =&gt; {
    let returnVal = '';
    render(
      &lt;Component value={value}&gt;
        {
          (val) =&gt; {
            returnVal = val;
            return null;
          }
        }
      &lt;/Component&gt;,
    );
    return returnVal;
  };
  
  describe('usePrevious', () =&gt; {
    it('returns something', () =&gt; {
      const test1 = setup('test');
      const test2 = setup(test1);
      expect(test2).toBe('test');
    });
  });
  </code></pre>
  
  <p>When the test execution completes, I get this error:</p>
  
  <pre><code>Expected: 'test', Received: undefined
  </code></pre>
  
  <p>Can anyone please let me know why am I getting undefined and is this the correct way to test custom hoooks in react?</p>
  
  <p><strong>After suggestion from comments from @Dmitrii G, I have changed my code to re-render the component (Previously I was re-mounting the component).</strong></p>
  
  <p>Here is the updated code:</p>
  
  <pre class="lang-js prettyprint-override"><code>import React from 'react';
  import PropTypes from 'prop-types';
  import { shallow } from 'enzyme';
  
  import { usePrevious } from './customHooks';
  
  const Component = ({ value }) =&gt; {
    const hookResult = usePrevious(value);
    return (
      &lt;div&gt;
        &lt;span&gt;{hookResult}&lt;/span&gt;
        &lt;span&gt;{value}&lt;/span&gt;
      &lt;/div&gt;
    );
  };
  
  Component.propTypes = {
    value: PropTypes.string,
  };
  
  Component.defaultProps = {
    value: '',
  };
  
  
  describe('usePrevious', () =&gt; {
    it('returns something', () =&gt; {
      const wrapper = shallow(&lt;Component value="test" /&gt;);
      console.log('&gt;&gt;&gt;&gt;&gt; first time', wrapper.find('div').childAt(1).text());
      expect(wrapper.find('div').childAt(0).text()).toBe('');
  
      // Test second render and effect
      wrapper.setProps({ value: 'test2' });
      console.log('&gt;&gt;&gt;&gt;&gt; second time', wrapper.find('div').childAt(1).text());
      expect(wrapper.find('div').childAt(0).text()).toBe('test');
    });
  });
  </code></pre>
  
  <p>But still I am getting the same error</p>
  
  <pre><code>Expected: "test", Received: ""
  </code></pre>
  
  <p><strong>Tests Passes when settimeout is introduced:</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>import React from 'react';
  import PropTypes from 'prop-types';
  import { shallow } from 'enzyme';
  
  import { usePrevious } from './customHooks';
  
  const Component = ({ value }) =&gt; {
    const hookResult = usePrevious(value);
    return &lt;span&gt;{hookResult}&lt;/span&gt;;
  };
  
  Component.propTypes = {
    value: PropTypes.string,
  };
  
  Component.defaultProps = {
    value: '',
  };
  
  
  describe('usePrevious', () =&gt; {
    it('returns empty string when component is rendered first time', () =&gt; {
      const wrapper = shallow(&lt;Component value="test" /&gt;);
      setTimeout(() =&gt; {
        expect(wrapper.find('span').text()).toBe('');
      }, 0);
    });
    it('returns previous value when component is re-rendered', () =&gt; {
      const wrapper = shallow(&lt;Component value="test" /&gt;);
      wrapper.setProps({ value: 'test2' });
      setTimeout(() =&gt; {
        expect(wrapper.find('span').text()).toBe('test');
      }, 0);
    });
  });
  </code></pre>
  
  <p>I am not a big fan of using settimeout, so I feel that probably i am doing some mistake. If anyone knows a solution that does not use settimeout, feel free to post here. Thank you.</p>