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

[renderHook] rerender with new props, new props are not consumed #964

Open
alextrastero opened this issue Jul 25, 2023 · 9 comments
Open

Comments

@alextrastero
Copy link

Passing new props to rerender doesn't work, please let me know if i'm doing anything wrong, thx

package.json

"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",

hook

export const useTriggerFocus = ({ condition = true, ref }: any): null => {
  console.log(condition);
  useEffect(() => {
    const element = ref.current;

    if (condition && element) {
      element?.focus();
    }
  }, [ref, condition]);

  return null;
};

test

  it('triggers a change', () => {
    const condition = false;
    const focus = vi.fn();
    const ref = {
      current: {
        focus,
      },
    };

    const { rerender } = renderHook(() => useTriggerFocus({ condition, ref }));

    rerender({ condition: true, ref: undefined });
    rerender();
    rerender();
    rerender();
  });
});

console

false
false
false
false
false
@cmorten
Copy link

cmorten commented Aug 5, 2023

Care needed to ensure that your renderHook is configured such that it knows what to do with the new props you pass into the rerender call.

E.g. something along the lines of (not tested)…

  it('triggers a change', () => {
    const initialProps = {
      condition: false,
      ref: {
        current: {
          focus: vi.fn(),
        },
      },
    };

    const { rerender } = renderHook(({ condition, ref }) => useTriggerFocus({ condition, ref }), { initialProps });

    rerender({ condition: true, ref: undefined });
  });
});

See the docs https://testing-library.com/docs/react-testing-library/api#rerender-1 for the syntax on how to make sure new props are used. Here I’ve also made use of the initialProps option https://testing-library.com/docs/react-testing-library/api#renderhook-options-initialprops.

At the moment your props passed to the rerender and being ignored as the renderHook callback is hardcoded to use those you defined at the beginning of your test.

P.S. your future queries for React Testing Library may be better placed in https://github.com/testing-library/react-testing-library or the discord than here as this is the Dom Testing Library repo! 🙃

P.P.S. take care when using a ref with useEffect - in a lot of use cases it doesn’t necessarily work, see https://epicreact.dev/why-you-shouldnt-put-refs-in-a-dependency-array/

@timdeschryver timdeschryver transferred this issue from testing-library/dom-testing-library Aug 14, 2023
@timdeschryver
Copy link
Member

This seems like a React Hooks Testing Library issue, I'm transferring this issue to the correct repository.

@alextrastero
Copy link
Author

Thanks @timdeschryver , do you have a link for that?

@timdeschryver
Copy link
Member

@alextrastero you don't have to take any action, we've already transferred it to the correct repository.
You can find it here, https://github.com/testing-library/react-hooks-testing-library

@mpeyper
Copy link
Member

mpeyper commented Nov 30, 2023

Hey, sorry I missed the notification that this one was transferred here.

Sorry to play ping pong again with your issue, but can you confirm if you are using renderHook from @testing-library/react-hooks (pre React 18, this repo) or @testing-library/react (React 18, RTL repo).

If it’s the latter, I’ll transfer it to the RTL repo.

Edit: quickly looking at the issue as if it was for our version, I’d say the solution presented by @cmorten above is correct.

@wellermiranda
Copy link

That worked for me:

const { rerender } = renderHook(useOverview, { initialProps });

@cmorten
Copy link

cmorten commented Jan 2, 2024

Update: Ah I was too slow, as you’ve posted!


The intended pattern is:

const { result, rerender } = renderHook((props = {}) => useMyHook(props), {
  initialProps,
});

expect(result.current).toEqual(firstResult);

rerender(newProps);

expect(result.current).toEqual(secondResult)

There should be no need to workaround - the key is to not hardcode the initialProps being passed to your hook, but instead allow props to be passed to the renderHook callback so passing values into rerender works as expected.

See the example in https://testing-library.com/docs/react-testing-library/api/#renderhook-options-initialprops, though appreciate it perhaps isn’t the most clear as the “hook” in the example is the identity function of reflecting the props back rather than something explicitly use* as most folks will implement.

@wellermiranda
Copy link

Thanks, @cmorten.

1 similar comment
@NotNikita
Copy link

Thanks, @cmorten.

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

7 participants
@wellermiranda @alextrastero @cmorten @mpeyper @timdeschryver @NotNikita and others