From 49c59a0d7dd9edd09e0890cee421118e1983efff Mon Sep 17 00:00:00 2001
From: Dhaya <154633+dhayab@users.noreply.github.com>
Date: Thu, 25 Aug 2022 17:36:29 +0200
Subject: [PATCH 1/2] feat(hooks): add remix example
---
react-instantsearch-hooks/remix/.eslintrc | 7 +
react-instantsearch-hooks/remix/.gitignore | 8 ++
react-instantsearch-hooks/remix/README.md | 53 ++++++++
.../remix/app/entry.client.tsx | 4 +
.../remix/app/entry.server.tsx | 21 +++
react-instantsearch-hooks/remix/app/root.tsx | 32 +++++
.../remix/app/routes/index.tsx | 122 ++++++++++++++++++
.../remix/components/Hit.tsx | 31 +++++
.../remix/components/NoResultsBoundary.tsx | 27 ++++
.../remix/components/Panel.tsx | 17 +++
.../remix/components/ScrollTo.tsx | 37 ++++++
.../remix/components/SearchErrorToast.tsx | 58 +++++++++
react-instantsearch-hooks/remix/package.json | 37 ++++++
.../remix/public/favicon.ico | Bin 0 -> 16958 bytes
.../remix/remix.config.js | 8 ++
.../remix/remix.env.d.ts | 2 +
.../remix/sandbox.config.json | 4 +
.../remix/tailwind.config.js | 8 ++
react-instantsearch-hooks/remix/tsconfig.json | 22 ++++
19 files changed, 498 insertions(+)
create mode 100644 react-instantsearch-hooks/remix/.eslintrc
create mode 100644 react-instantsearch-hooks/remix/.gitignore
create mode 100644 react-instantsearch-hooks/remix/README.md
create mode 100644 react-instantsearch-hooks/remix/app/entry.client.tsx
create mode 100644 react-instantsearch-hooks/remix/app/entry.server.tsx
create mode 100644 react-instantsearch-hooks/remix/app/root.tsx
create mode 100644 react-instantsearch-hooks/remix/app/routes/index.tsx
create mode 100644 react-instantsearch-hooks/remix/components/Hit.tsx
create mode 100644 react-instantsearch-hooks/remix/components/NoResultsBoundary.tsx
create mode 100644 react-instantsearch-hooks/remix/components/Panel.tsx
create mode 100644 react-instantsearch-hooks/remix/components/ScrollTo.tsx
create mode 100644 react-instantsearch-hooks/remix/components/SearchErrorToast.tsx
create mode 100644 react-instantsearch-hooks/remix/package.json
create mode 100644 react-instantsearch-hooks/remix/public/favicon.ico
create mode 100644 react-instantsearch-hooks/remix/remix.config.js
create mode 100644 react-instantsearch-hooks/remix/remix.env.d.ts
create mode 100644 react-instantsearch-hooks/remix/sandbox.config.json
create mode 100644 react-instantsearch-hooks/remix/tailwind.config.js
create mode 100644 react-instantsearch-hooks/remix/tsconfig.json
diff --git a/react-instantsearch-hooks/remix/.eslintrc b/react-instantsearch-hooks/remix/.eslintrc
new file mode 100644
index 0000000000..63c8720ab8
--- /dev/null
+++ b/react-instantsearch-hooks/remix/.eslintrc
@@ -0,0 +1,7 @@
+{
+ "extends": ["@remix-run/eslint-config", "@remix-run/eslint-config/node"],
+ "rules": {
+ "@typescript-eslint/naming-convention": "off",
+ "spaced-comment": ["error", "always", { "markers": ["/"] }]
+ }
+}
diff --git a/react-instantsearch-hooks/remix/.gitignore b/react-instantsearch-hooks/remix/.gitignore
new file mode 100644
index 0000000000..5f2cb537b5
--- /dev/null
+++ b/react-instantsearch-hooks/remix/.gitignore
@@ -0,0 +1,8 @@
+node_modules
+
+/.cache
+/build
+/public/build
+.env
+
+/app/tailwind.css
diff --git a/react-instantsearch-hooks/remix/README.md b/react-instantsearch-hooks/remix/README.md
new file mode 100644
index 0000000000..9659e785e0
--- /dev/null
+++ b/react-instantsearch-hooks/remix/README.md
@@ -0,0 +1,53 @@
+# Welcome to Remix!
+
+- [Remix Docs](https://remix.run/docs)
+
+## Development
+
+From your terminal:
+
+```sh
+npm run dev
+```
+
+This starts your app in development mode, rebuilding assets on file changes.
+
+## Deployment
+
+First, build your app for production:
+
+```sh
+npm run build
+```
+
+Then run the app in production mode:
+
+```sh
+npm start
+```
+
+Now you'll need to pick a host to deploy it to.
+
+### DIY
+
+If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
+
+Make sure to deploy the output of `remix build`
+
+- `build/`
+- `public/build/`
+
+### Using a Template
+
+When you ran `npx create-remix@latest` there were a few choices for hosting. You can run that again to create a new project, then copy over your `app/` folder to the new project that's pre-configured for your target server.
+
+```sh
+cd ..
+# create a new project, and pick a pre-configured host
+npx create-remix@latest
+cd my-new-remix-app
+# remove the new project's app (not the old one!)
+rm -rf app
+# copy your app over
+cp -R ../my-old-remix-app/app app
+```
diff --git a/react-instantsearch-hooks/remix/app/entry.client.tsx b/react-instantsearch-hooks/remix/app/entry.client.tsx
new file mode 100644
index 0000000000..e313b977e5
--- /dev/null
+++ b/react-instantsearch-hooks/remix/app/entry.client.tsx
@@ -0,0 +1,4 @@
+import { RemixBrowser } from '@remix-run/react';
+import { hydrateRoot } from 'react-dom/client';
+
+hydrateRoot(document, );
diff --git a/react-instantsearch-hooks/remix/app/entry.server.tsx b/react-instantsearch-hooks/remix/app/entry.server.tsx
new file mode 100644
index 0000000000..9e20196f54
--- /dev/null
+++ b/react-instantsearch-hooks/remix/app/entry.server.tsx
@@ -0,0 +1,21 @@
+import type { EntryContext } from '@remix-run/node';
+import { RemixServer } from '@remix-run/react';
+import { renderToString } from 'react-dom/server';
+
+export default function handleRequest(
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext
+) {
+ const markup = renderToString(
+
+ );
+
+ responseHeaders.set('Content-Type', 'text/html');
+
+ return new Response(`${markup}`, {
+ status: responseStatusCode,
+ headers: responseHeaders,
+ });
+}
diff --git a/react-instantsearch-hooks/remix/app/root.tsx b/react-instantsearch-hooks/remix/app/root.tsx
new file mode 100644
index 0000000000..f7c19e7e52
--- /dev/null
+++ b/react-instantsearch-hooks/remix/app/root.tsx
@@ -0,0 +1,32 @@
+import type { MetaFunction } from '@remix-run/node';
+import {
+ Links,
+ LiveReload,
+ Meta,
+ Outlet,
+ Scripts,
+ ScrollRestoration,
+} from '@remix-run/react';
+
+export const meta: MetaFunction = () => ({
+ charset: 'utf-8',
+ title: 'React InstantSearch Hooks - Remix',
+ viewport: 'width=device-width,initial-scale=1',
+});
+
+export default function App() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/react-instantsearch-hooks/remix/app/routes/index.tsx b/react-instantsearch-hooks/remix/app/routes/index.tsx
new file mode 100644
index 0000000000..dff17af99e
--- /dev/null
+++ b/react-instantsearch-hooks/remix/app/routes/index.tsx
@@ -0,0 +1,122 @@
+import algoliasearch from 'algoliasearch/lite';
+import type { InstantSearchServerState } from 'react-instantsearch-hooks-web';
+import {
+ DynamicWidgets,
+ Hits,
+ InstantSearch,
+ InstantSearchSSRProvider,
+ Pagination,
+ RefinementList,
+ SearchBox,
+ useInstantSearch,
+} from 'react-instantsearch-hooks-web';
+import { getServerState } from 'react-instantsearch-hooks-server';
+import { history } from 'instantsearch.js/cjs/lib/routers/index.js';
+import instantSearchStyles from 'instantsearch.css/themes/satellite-min.css';
+
+import type { LinksFunction, LoaderFunction } from '@remix-run/node';
+import { json } from '@remix-run/node';
+import { useLoaderData } from '@remix-run/react';
+
+import { Hit } from '../../components/Hit';
+import { Panel } from '../../components/Panel';
+import { ScrollTo } from '../../components/ScrollTo';
+import { NoResultsBoundary } from '../../components/NoResultsBoundary';
+import { SearchErrorToast } from '../../components/SearchErrorToast';
+
+import tailwindStyles from '../tailwind.css';
+
+const searchClient = algoliasearch(
+ 'latency',
+ '6be0576ff61c053d5f9a3225e2a90f76'
+);
+
+export const links: LinksFunction = () => [
+ { rel: 'stylesheet', href: instantSearchStyles },
+ { rel: 'stylesheet', href: tailwindStyles },
+];
+
+export const loader: LoaderFunction = async ({ request }) => {
+ const serverUrl = request.url;
+ const serverState = await getServerState();
+
+ return json({
+ serverState,
+ serverUrl,
+ });
+};
+
+type SearchProps = {
+ serverState?: InstantSearchServerState;
+ serverUrl?: string;
+};
+
+function Search({ serverState, serverUrl }: SearchProps) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function FallbackComponent({ attribute }: { attribute: string }) {
+ return (
+
+
+
+ );
+}
+
+function NoResults() {
+ const { indexUiState } = useInstantSearch();
+
+ return (
+
+
+ No results for {indexUiState.query}
.
+
+
+ );
+}
+
+export default function HomePage() {
+ const { serverState, serverUrl } = useLoaderData();
+
+ return ;
+}
diff --git a/react-instantsearch-hooks/remix/components/Hit.tsx b/react-instantsearch-hooks/remix/components/Hit.tsx
new file mode 100644
index 0000000000..07741f6af9
--- /dev/null
+++ b/react-instantsearch-hooks/remix/components/Hit.tsx
@@ -0,0 +1,31 @@
+import type { Hit as AlgoliaHit } from 'instantsearch.js';
+import { Highlight } from 'react-instantsearch-hooks-web';
+
+type HitProps = {
+ hit: AlgoliaHit<{
+ name: string;
+ price: number;
+ image: string;
+ brand: string;
+ }>;
+};
+
+export function Hit({ hit }: HitProps) {
+ return (
+
+
+

+
+
+
+
+
+
{hit.brand}
+
${hit.price}
+
+ );
+}
diff --git a/react-instantsearch-hooks/remix/components/NoResultsBoundary.tsx b/react-instantsearch-hooks/remix/components/NoResultsBoundary.tsx
new file mode 100644
index 0000000000..cf7f6090c1
--- /dev/null
+++ b/react-instantsearch-hooks/remix/components/NoResultsBoundary.tsx
@@ -0,0 +1,27 @@
+import type { ReactNode } from 'react';
+import { useInstantSearch } from 'react-instantsearch-hooks-web';
+
+type NoResultsBoundaryProps = {
+ children: ReactNode;
+ fallback: ReactNode;
+};
+
+export function NoResultsBoundary({
+ children,
+ fallback,
+}: NoResultsBoundaryProps) {
+ const { results } = useInstantSearch();
+
+ // The `__isArtificial` flag makes sure to not display the No Results message
+ // when no hits have been returned yet.
+ if (!results.__isArtificial && results.nbHits === 0) {
+ return (
+ <>
+ {fallback}
+ {children}
+ >
+ );
+ }
+
+ return <>{children}>;
+}
diff --git a/react-instantsearch-hooks/remix/components/Panel.tsx b/react-instantsearch-hooks/remix/components/Panel.tsx
new file mode 100644
index 0000000000..1fdd24737a
--- /dev/null
+++ b/react-instantsearch-hooks/remix/components/Panel.tsx
@@ -0,0 +1,17 @@
+export function Panel({
+ children,
+ header,
+ footer,
+}: {
+ children: React.ReactNode;
+ header?: React.ReactNode;
+ footer?: React.ReactNode;
+}) {
+ return (
+
+ {header &&
{header}
}
+
{children}
+ {footer &&
{footer}
}
+
+ );
+}
diff --git a/react-instantsearch-hooks/remix/components/ScrollTo.tsx b/react-instantsearch-hooks/remix/components/ScrollTo.tsx
new file mode 100644
index 0000000000..2916c42426
--- /dev/null
+++ b/react-instantsearch-hooks/remix/components/ScrollTo.tsx
@@ -0,0 +1,37 @@
+import type { ComponentProps, ReactNode } from 'react';
+import React, { useEffect, useRef } from 'react';
+import { useInstantSearch } from 'react-instantsearch-hooks-web';
+
+type ScrollToProps = ComponentProps<'div'> & {
+ children: ReactNode;
+};
+
+export function ScrollTo({ children, ...props }: ScrollToProps) {
+ const { use } = useInstantSearch();
+ const containerRef = useRef(null);
+
+ useEffect(() => {
+ return use(() => {
+ return {
+ onStateChange() {
+ const isFiltering = document.body.classList.contains('filtering');
+ const isTyping =
+ document.activeElement?.tagName === 'INPUT' &&
+ document.activeElement?.getAttribute('type') === 'search';
+
+ if (isFiltering || isTyping) {
+ return;
+ }
+
+ containerRef.current!.scrollIntoView();
+ },
+ };
+ });
+ }, [use]);
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/react-instantsearch-hooks/remix/components/SearchErrorToast.tsx b/react-instantsearch-hooks/remix/components/SearchErrorToast.tsx
new file mode 100644
index 0000000000..7b7a9cd5a6
--- /dev/null
+++ b/react-instantsearch-hooks/remix/components/SearchErrorToast.tsx
@@ -0,0 +1,58 @@
+import React, { useEffect, useState } from 'react';
+import * as Toast from '@radix-ui/react-toast';
+import { useInstantSearch } from 'react-instantsearch-hooks-web';
+
+export function SearchErrorToast() {
+ const { use } = useInstantSearch();
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ return use(({ instantSearchInstance }) => {
+ function handleError(searchError: Error) {
+ setError(searchError);
+ }
+
+ return {
+ subscribe() {
+ instantSearchInstance.addListener('error', handleError);
+ },
+ unsubscribe() {
+ instantSearchInstance.removeListener('error', handleError);
+ },
+ };
+ });
+ }, [use]);
+
+ if (!error) {
+ return null;
+ }
+
+ return (
+
+ {
+ if (!isOpen) {
+ setError(null);
+ }
+ }}
+ >
+
+
+
+
+
+ {error.name}
+
+
+ {error.message}
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/react-instantsearch-hooks/remix/package.json b/react-instantsearch-hooks/remix/package.json
new file mode 100644
index 0000000000..5ada9113d5
--- /dev/null
+++ b/react-instantsearch-hooks/remix/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "hooks-remix-example",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "build": "run-s \"build:*\"",
+ "build:css": "yarn run generate:css --minify",
+ "build:remix": "remix build",
+ "dev": "run-p \"dev:*\"",
+ "dev:css": "yarn run generate:css --watch",
+ "dev:remix": "remix dev",
+ "generate:css": "npx tailwindcss -o ./app/tailwind.css",
+ "start": "remix-serve build"
+ },
+ "dependencies": {
+ "@radix-ui/react-toast": "0.1.1",
+ "@remix-run/node": "1.6.5",
+ "@remix-run/react": "1.6.5",
+ "@remix-run/serve": "1.6.5",
+ "algoliasearch": "4.11.0",
+ "instantsearch.css": "7.4.5",
+ "react": "18.1.0",
+ "react-dom": "18.1.0",
+ "react-instantsearch-hooks-server": "6.30.2",
+ "react-instantsearch-hooks-web": "6.30.2"
+ },
+ "devDependencies": {
+ "@remix-run/dev": "1.6.5",
+ "@remix-run/eslint-config": "1.6.5",
+ "npm-run-all": "4.1.5",
+ "tailwindcss": "3.1.6",
+ "typescript": "4.7.4"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+}
diff --git a/react-instantsearch-hooks/remix/public/favicon.ico b/react-instantsearch-hooks/remix/public/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..8830cf6821b354114848e6354889b8ecf6d2bc61
GIT binary patch
literal 16958
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
EKbET!0{{R3
literal 0
HcmV?d00001
diff --git a/react-instantsearch-hooks/remix/remix.config.js b/react-instantsearch-hooks/remix/remix.config.js
new file mode 100644
index 0000000000..2eee2ab3f5
--- /dev/null
+++ b/react-instantsearch-hooks/remix/remix.config.js
@@ -0,0 +1,8 @@
+/** @type {import('@remix-run/dev').AppConfig} */
+module.exports = {
+ ignoredRouteFiles: ['**/.*'],
+ // appDirectory: "app",
+ // assetsBuildDirectory: "public/build",
+ // serverBuildPath: "build/index.js",
+ // publicPath: "/build/",
+};
diff --git a/react-instantsearch-hooks/remix/remix.env.d.ts b/react-instantsearch-hooks/remix/remix.env.d.ts
new file mode 100644
index 0000000000..72e2affe31
--- /dev/null
+++ b/react-instantsearch-hooks/remix/remix.env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/react-instantsearch-hooks/remix/sandbox.config.json b/react-instantsearch-hooks/remix/sandbox.config.json
new file mode 100644
index 0000000000..be139c9097
--- /dev/null
+++ b/react-instantsearch-hooks/remix/sandbox.config.json
@@ -0,0 +1,4 @@
+{
+ "template": "node",
+ "container": { "port": 3000, "startScript": "dev" }
+}
\ No newline at end of file
diff --git a/react-instantsearch-hooks/remix/tailwind.config.js b/react-instantsearch-hooks/remix/tailwind.config.js
new file mode 100644
index 0000000000..f7b2a44a53
--- /dev/null
+++ b/react-instantsearch-hooks/remix/tailwind.config.js
@@ -0,0 +1,8 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ['./app/**/*.{ts,tsx,jsx,js}', './components/**/*.{ts,tsx,jsx,js}'],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+};
diff --git a/react-instantsearch-hooks/remix/tsconfig.json b/react-instantsearch-hooks/remix/tsconfig.json
new file mode 100644
index 0000000000..20f8a386a6
--- /dev/null
+++ b/react-instantsearch-hooks/remix/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
+ "compilerOptions": {
+ "lib": ["DOM", "DOM.Iterable", "ES2019"],
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "target": "ES2019",
+ "strict": true,
+ "allowJs": true,
+ "forceConsistentCasingInFileNames": true,
+ "baseUrl": ".",
+ "paths": {
+ "~/*": ["./app/*"]
+ },
+
+ // Remix takes care of building everything in `remix build`.
+ "noEmit": true
+ }
+}
From 1e6a5a37814b5a26f32df9a24ed22638ed9110cb Mon Sep 17 00:00:00 2001
From: Dhaya <154633+dhayab@users.noreply.github.com>
Date: Fri, 26 Aug 2022 13:12:21 +0200
Subject: [PATCH 2/2] add react types in dev dependencies
---
react-instantsearch-hooks/remix/package.json | 2 ++
1 file changed, 2 insertions(+)
diff --git a/react-instantsearch-hooks/remix/package.json b/react-instantsearch-hooks/remix/package.json
index 5ada9113d5..b2e2f0e2b1 100644
--- a/react-instantsearch-hooks/remix/package.json
+++ b/react-instantsearch-hooks/remix/package.json
@@ -27,6 +27,8 @@
"devDependencies": {
"@remix-run/dev": "1.6.5",
"@remix-run/eslint-config": "1.6.5",
+ "@types/react": "18.0.17",
+ "@types/react-dom": "18.0.6",
"npm-run-all": "4.1.5",
"tailwindcss": "3.1.6",
"typescript": "4.7.4"