Skip to content

Commit

Permalink
Add ExistingSearchParams util (sergiodxa#279)
Browse files Browse the repository at this point in the history
Adds `ExistingSearchParams` from
https://www.jacobparis.com/content/existing-params

I'll update my article once this is published

Let me know if I've missed any steps here
  • Loading branch information
jacobparis authored Nov 24, 2023
1 parent 5c61c3c commit 88e9159
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 0 deletions.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,49 @@ You can use `error.code` to check one of the error codes above, and `error.messa
> **Warning**
> Don't send those error messages to the end-user, they are meant to be used for debugging purposes only.
### Existing Search Params

```ts
import { ExistingSearchParams } from "remix-utils/existing-search-params";
```

> **Note**
> This depends on `react` and `@remix-run/react`
When you submit a GET form, the browser will replace all of the search params in the URL with your form data. This component copies existing search params into hidden inputs so they will not be overwritten.

The `exclude` prop accepts an array of search params to exclude from the hidden inputs

- add params handled by this form to this list
- add params from other forms you want to clear on submit

For example, imagine a table of data with separate form components for pagination and filtering and searching. Changing the page number should not affect the search or filter params.

```tsx
<Form>
<ExistingSearchParams exclude={["page"]} />
<button type="submit" name="page" value="1">
1
</button>
<button type="submit" name="page" value="2">
2
</button>
<button type="submit" name="page" value="3">
3
</button>
</Form>
```

By excluding the `page` param, from the search form, the user will return to the first page of search result.

```tsx
<Form>
<ExistingSearchParams exclude={["q", "page"]} />
<input type="search" name="q" />
<button type="submit">Search</button>
</Form>
```

### External Scripts

> **Note**
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"./typed-cookie": "./build/server/typed-cookie.js",
"./typed-session": "./build/server/typed-session.js",
"./client-only": "./build/react/client-only.js",
"./existing-search-params": "./build/react/existing-search-params.js",
"./external-scripts": "./build/react/external-scripts.js",
"./fetcher-type": "./build/react/fetcher-type.js",
"./server-only": "./build/react/server-only.js",
Expand Down
56 changes: 56 additions & 0 deletions src/react/existing-search-params.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as React from "react";
import { useSearchParams } from "@remix-run/react";

type Props = {
/**
* These query params will not be included as hidden inputs.
* - add params handled by this form to this list
* - any params from other forms you want to clear on submit
*/
exclude?: Array<string | undefined>;
};

/**
* Include existing query params as hidden inputs in a form.
*
* @example
* A pagination bar that does not clear the search query
* ```tsx
* <Form>
* <ExistingSearchParams exclude={['page']} />
* <button type="submit" name="page" value="1">1</button>
* <button type="submit" name="page" value="2">2</button>
* <button type="submit" name="page" value="3">3</button>
* </Form>
* ```
*
* @example
* A search form that clears the page param
* ```tsx
* <Form>
* <ExistingSearchParams exclude={['q', 'page']} />
* <input type="search" name="q" />
* </Form>
* ```
*/
export function ExistingSearchParams({ exclude }: Props) {
const [searchParams] = useSearchParams();
const existingSearchParams = [...searchParams.entries()].filter(
([key]) => !exclude?.includes(key),
);

return (
<>
{existingSearchParams.map(([key, value]) => {
return (
<input
key={`${key}=${value}`}
type="hidden"
name={key}
value={value}
/>
);
})}
</>
);
}

0 comments on commit 88e9159

Please sign in to comment.