title: Calling prop callback in react test renderer doesn't update hooks
body: <p>I'm trying to figure out how to test a react function component that uses hooks to keep track of state. The problem I'm having is when I call the <code>onChange</code> prop function passed to the input components, the value of my <code>useState</code> hook isn't being updated, so when I trigger the form submit, the result doesn't reflect the state changes.</p>
  
  <p>Here is the component I'm testing:</p>
  
  <pre><code>import React, { useState, ChangeEvent, FormEvent } from 'react';
  import styled from '../styled';
  import Column from './Column';
  import BlockButton from './BlockButton';
  import Input from './Input';
  import Form from './Form';
  import InputRow from './InputRow';
  
  export type LoginFormOnSubmit = (result: LoginFormResult) =&gt; any;
  export interface LoginFormResult {
    employeeId: string;
    password: string;
  }
  export interface LoginFormProps {
    onSubmit?: LoginFormOnSubmit;
  }
  
  const LoginForm: React.FunctionComponent&lt;LoginFormProps&gt; = props =&gt; {
    const { onSubmit, ...rest } = props;
    const [employeeId, setEmployeeId] = useState('');
    const [password, setPassword] = useState('');
  
    function handleEmployeeIdChange(event: ChangeEvent&lt;HTMLInputElement&gt;) {
      setEmployeeId(event.currentTarget.value);
    }
  
    function handlePasswordChange(event: ChangeEvent&lt;HTMLInputElement&gt;) {
      setPassword(event.currentTarget.value);
    }
  
    function handleSubmit(event: FormEvent&lt;HTMLFormElement&gt;) {
      if(onSubmit) {
        onSubmit({
          employeeId,
          password,
        });
      }
    }
  
    return (
      &lt;Column {...rest}&gt;
        &lt;h1&gt;SHIFT LEDGER LOGON&lt;/h1&gt;
        &lt;Form onSubmit={handleSubmit}&gt;
          &lt;InputRow&gt;
            &lt;label&gt;Employee ID:&lt;/label&gt;
            &lt;Input
              type="text"
              value={employeeId}
              onChange={handleEmployeeIdChange}
              data-testid="employee-id-input"
            /&gt;
          &lt;/InputRow&gt;
          &lt;InputRow&gt;
            &lt;label&gt;Password:&lt;/label&gt;
            &lt;Input
              type="password"
              value={password}
              onChange={handlePasswordChange}
              data-test-id="password-input"
            /&gt;
          &lt;/InputRow&gt;
          &lt;BlockButton data-testid="submit-button"&gt;Enter&lt;/BlockButton&gt;
        &lt;/Form&gt;
      &lt;/Column&gt;
    );
  };
  
  export default styled(LoginForm)`
    background-color: #F0EBDF;
    justify-content: center;
    flex: 1;
  
    h1 {
      text-align: center;
    }
  
    ${Form} {
      align-items: center;
    }
  
    label {
      width: 150px;
    }
  `;
  </code></pre>
  
  <p>And here is my test:</p>
  
  <pre><code>import React from 'react';
  import sinon from 'sinon';
  import TestRenderer, { act } from 'react-test-renderer';
  import LoginForm from '../LoginForm';
  import Form from '../Form';
  
  describe('components/LoginForm', () =&gt; {
    test('Should be able to edit employee id', async () =&gt; {
      const onSubmit = sinon.fake();
      const employeeId = 'test id';
      const rendered = TestRenderer.create(&lt;LoginForm onSubmit={onSubmit}/&gt;);
  
  
      act(() =&gt; {
        const wrapper = rendered.root;
        const employeeIdInput = wrapper.findByProps({ 'data-testid': 'employee-id-input' });
  
        employeeIdInput.props!.onChange({
          currentTarget: {
            value: employeeId,
          },
        });
  
        wrapper.findByType(Form).props.onSubmit({
          preventDefault: sinon.fake(),
        });
      });
  
      expect(onSubmit.calledOnce).toBeTruthy();
      expect(onSubmit.args).toEqual([[
        {
          employeeId,
          password: '',
        }
      ]]);
    });
  });
  </code></pre>
  
  <p>And the error I'm seeing:</p>
  
  <pre><code>  ● components/LoginForm › Should be able to edit employee id
  
      expect(received).toEqual(expected)
  
      Difference:
  
      - Expected
      + Received
  
        Array [
          Array [
            Object {
      -       "employeeId": "test id",
      +       "employeeId": "",
              "password": "",
            },
          ],
        ]
  
        42 |     });
        43 |
      &gt; 44 |     expect(onSubmit.calledOnce).toBeTruthy();
           |                                 ^
        45 |     expect(onSubmit.args).toEqual([[
        46 |       {
        47 |         employeeId,
  
        at react_test_renderer_1.act (src/components/__tests__/LoginForm.test.tsx:44:33)
        at batchedUpdates (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12492:12)
        at Object.act (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13146:18)
        at Object.test (src/components/__tests__/LoginForm.test.tsx:29:5)
  </code></pre>
  
  <p>Some extra info:</p>
  
  <ul>
  <li>typescript 3.3.3</li>
  <li>react 16.8.2</li>
  <li>react-dom 16.8.2</li>
  <li>react-test-renderer 16.8.5</li>
  <li>jest 24.3.1</li>
  </ul>