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

feat(remix-react): add submitOptions argument for useSubmit and useFetcher #4882

Closed
wants to merge 10 commits into from

Conversation

kentcdodds
Copy link
Member

@kentcdodds kentcdodds commented Dec 15, 2022

This fixes an actual bug I was having when trying to use a fetcher in a useEffect. It's also a handy API that I've seen people ask for as well.

Closes: #4872

  • Docs
  • Tests

Testing Strategy: Automated Integration test

This is just pushing the failing test to demonstrate the issue.

The issue is actually technically correct behavior, but I need a new feature to accomplish what I want so I'll be changing the test once this new API is supported. I'm working on that next.

Implementation is finished and documented. Ready to discuss/merge.

Until this is merged, the only way to reliably use a fetcher.submit in a dep array is to do something like this:

const fetcher = useFetcher()
const submitRef = useRef(fetcher.submit)
useEffect(() => {
  submitRef.current = fetcher.submit
})
React.useEffect(() => {
  // can safely use submitRef without including in dep array
  submitRef({other, deps}, {action: '/some-path', method: 'post'})
}, [other, deps])

The drawback here is that if we actually do depend on the defaultAction then it's possible we'll get the wrong one when submit is called.

This PR fixes that by allowing users to specify an action (among other submit options):

const fetcher = useFetcher({action: '/some-path', method: 'post'})
React.useEffect(() => {
  // can safely include fetcher in dep array
  fetcher.submit({other, deps})
}, [other, deps, fetcher])

@changeset-bot
Copy link

changeset-bot bot commented Dec 15, 2022

🦋 Changeset detected

Latest commit: 354482b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
remix Minor
@remix-run/react Minor
@remix-run/testing Minor
create-remix Minor
@remix-run/architect Minor
@remix-run/cloudflare Minor
@remix-run/cloudflare-pages Minor
@remix-run/cloudflare-workers Minor
@remix-run/deno Minor
@remix-run/dev Minor
@remix-run/eslint-config Minor
@remix-run/express Minor
@remix-run/netlify Minor
@remix-run/node Minor
@remix-run/serve Minor
@remix-run/server-runtime Minor
@remix-run/vercel Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@kentcdodds kentcdodds changed the title add failing test Add submitOptions argument for useSubmit and useFetcher Dec 15, 2022
@machour
Copy link
Collaborator

machour commented Dec 15, 2022

Remember to target the dev branch 🙏

packages/remix-react/components.tsx Outdated Show resolved Hide resolved
export function useSubmit(): SubmitFunction {
return useSubmitImpl();
export function useSubmit(options?: SubmitOptions): SubmitFunction {
let key = undefined; // no key for global submit
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about making key a part of the options object in useSubmitImpl instead of accepting it as a first param, but decided to not cause a breaking change to useSubmitImpl because it's exported and it's possible people are using it. I actually don't hate this though so maybe it's fine?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I think we can safely remove the export (as it was never intended to be a public API), I think we can make key part of the submitOptions

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually kinda like that submitOptions is a separate argument, even though we have this funny key = undefined thing. But I don't care enough.

Comment on lines +1256 to +1265
const DEFAULT_METHOD = "get";
const DEFAULT_ENC_TYPE = "application/x-www-form-urlencoded";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched these to const and upper-case because otherwise typescript wasn't happy about default-assigning submitMethod to DEFAULT_METHOD below. Using const here allows typescript to narrow this down from a type of string to "get" which fits in the FormMethod type.

Comment on lines +1270 to +1281
let defaultFormAction = useFormAction();
let defaultAction = submitAction || defaultFormAction;
let defaultMethod = submitMethod || DEFAULT_METHOD;
let defaultEncType = submitEncType || DEFAULT_ENC_TYPE;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By putting these calculations all here we can avoid having to pass defaultFormAction into the dependency array which is what fixes my original issue.

packages/remix-react/components.tsx Show resolved Hide resolved
@kentcdodds kentcdodds changed the base branch from main to dev December 15, 2022 20:31
@kentcdodds
Copy link
Member Author

Sorry, totally forgot to target dev. Thanks for the tip @machour. I've fixed it up.

@MichaelDeBoey MichaelDeBoey changed the title Add submitOptions argument for useSubmit and useFetcher feat(remix-react): add submitOptions argument for useSubmit and useFetcher Dec 15, 2022
Co-authored-by: Michaël De Boey <info@michaeldeboey.be>
@brophdawg11
Copy link
Contributor

We're about to wipe this code out when we merge the 6.4 work 😬 - so if we're going to adopt this we probably need to do it in react-router-dom. Could we open a proposal for this API enhancement? Get enough upvotes and it could be accepted as soon as Monday!

@kentcdodds
Copy link
Member Author

Yep. I expected as much. Didn't really think this would get merged as-is. Here's the discussion over there: remix-run/react-router#9737

@machour
Copy link
Collaborator

machour commented Jan 22, 2023

Closing this as it will be implemented in RR

@machour machour closed this Jan 22, 2023
@MichaelDeBoey MichaelDeBoey deleted the pr-fetcher-search-params branch January 22, 2023 23:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Revalidation triggers fetcher.submit to change
4 participants