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

Solid adapter #25

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/react-stub/reference-app/components/TaskItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Link, useFetcher } from "react-router-dom";
import { Link, useFetcher, } from "react-router-dom";

import type { Task } from "../tasks";

Expand All @@ -8,7 +8,7 @@ export interface TaskItemProps {

export default function TaskItem({ task }: TaskItemProps) {
let fetcher = useFetcher();
let isDeleting = fetcher.formData != null;
let isDeleting = fetcher.formData != null;
Copy link
Owner

Choose a reason for hiding this comment

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

I think changes to this file are unintended :)


return (
<>
Expand Down
2 changes: 2 additions & 0 deletions packages/solid/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
34 changes: 34 additions & 0 deletions packages/solid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## Usage
Copy link
Owner

Choose a reason for hiding this comment

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

Let's update this with something like what Vue/Svelte has that shows an example of how to use this in a new Solid app


Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.

This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template.

```bash
$ npm install # or pnpm install or yarn install
```

### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)

## Available Scripts

In the project directory, you can run:

### `npm dev` or `npm start`

Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.<br>

### `npm run build`

Builds the app for production to the `dist` folder.<br>
It correctly bundles Solid in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!

## Deployment

You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)
16 changes: 16 additions & 0 deletions packages/solid/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
<title>Solid App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>

<script src="/referance-app/index.tsx" type="module"></script>
</body>
</html>
26 changes: 26 additions & 0 deletions packages/solid/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "remix-router-solid",
"version": "0.0.0",
"description": "",
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"integration:open": "cypress open --config-file ../../cypress.config.ts",
"integration:start": "vite --mode=production --port 3000",
"integration:test": "cypress run --config-file ../../cypress.config.ts",
"integration": "start-server-and-test integration:start http-get://localhost:3000/ integration:test",
"prepublishOnly": "rm -rf dist && npm run build"
},
"license": "MIT",
"devDependencies": {
"typescript": "^4.9.4",
"vite": "^4.0.3",
Comment on lines +18 to +19
Copy link
Owner

Choose a reason for hiding this comment

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

Out of curiosity, do we need these updated versions for Solid? Or would the versions installed in the repo root package.json suffice? If these are required for Solid then no worries and eventually I'll get the root versions updated and we can drop these from the dependencies.

"vite-plugin-solid": "^2.5.0"
},
"dependencies": {
"@remix-run/router": "0.2.0-pre.10",
Copy link
Owner

Choose a reason for hiding this comment

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

This has been released as stable since the repo was created. I wouldn't touch anything in this initial PR - but maybe in a follow up we can get it onto the latest (1.2.1, soon to be 1.3.0)

"solid-js": "^1.6.6"
}
}
69 changes: 69 additions & 0 deletions packages/solid/referance-app/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import type { Component } from "solid-js";
Copy link
Owner

Choose a reason for hiding this comment

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

Small typo in the folder name her - reference-app

import {
createBrowserRouter,
RouteObject,
RouterProvider,
} from "remix-router-solid";
import { Root } from "./routes/Root";
import { Index } from "./routes/Index";
import { Parent, parentLoader } from "./routes/nested/parent";
import { Child, childLoader } from "./routes/nested/child";
import { Boundary } from "./components/Boundary";
import { ErrorComp, errorLoader } from "./routes/Error";
import { Redirect, redirectLoader } from "./routes/Redirect";
import { Defer, deferLoader } from "./routes/Defer";
import { Tasks, tasksAction, tasksLoader } from "./routes/tasks/Tasks";
import { Task, taskLoader } from "./routes/tasks/Task";
import { NewTask, newTaskAction } from "./routes/tasks/NewTask";

export const App: Component = () => {
const routes: RouteObject[] = [
{
path: "/",
element: Root,
children: [
{ index: true, element: Index },
{
path: "parent",
element: Parent,
loader: parentLoader,
errorElement: Boundary,
children: [
{ path: "child", element: Child, loader: childLoader },
{ path: "error", loader: errorLoader, element: ErrorComp },
],
},
{ path: "error", loader: errorLoader, element: ErrorComp },
{ path: "redirect", loader: redirectLoader, element: Redirect },
{
path: "defer",
loader: deferLoader,
element: Defer,
},
{
path: "tasks",
loader: tasksLoader,
action: tasksAction,
element: Tasks,
children: [
{
path: ":id",
loader: taskLoader,
element: Task,
},
{ path: "new", action: newTaskAction, element: NewTask },
],
},
],
},
];

const router = createBrowserRouter(routes);

const fetcher1 = router.getFetcher("1");
const fetcher2 = router.getFetcher("2");

Comment on lines +63 to +65
Copy link
Owner

Choose a reason for hiding this comment

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

Unused?


return <RouterProvider router={router} />;
};

13 changes: 13 additions & 0 deletions packages/solid/referance-app/components/Boundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Link, useRouteError } from "remix-router-solid";

export const Boundary = () => {
const error = useRouteError() as () => Error;

return (
<>
<h2>Application Error Boundary</h2>
<p>{error().message}</p>
<Link to="/">Go home</Link>
</>
);
};
32 changes: 32 additions & 0 deletions packages/solid/referance-app/components/TaskItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Link, useFetcher } from "remix-router-solid";

import type { Task } from "../tasks";

export interface TaskItemProps {
task: Task;
}

export const TaskItem = ({ task }: TaskItemProps) => {
let fetcher = useFetcher();
let isDeleting = () => {
return fetcher().formData != null
};
const Form = fetcher().Form

return (
<>
<span>{task.task}</span> <Link to={`/tasks/${task.id}`}>Open</Link>{" "}
<Form style={{ display: "inline" }} action="/tasks" method="post">
<button
type="submit"
name="taskId"
value={task.id}
disabled={isDeleting()}
>
{isDeleting() ? "Deleting..." : "❌"}
</button>
</Form>
</>
);
}

6 changes: 6 additions & 0 deletions packages/solid/referance-app/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* @refresh reload */
import { render } from "solid-js/web";
import { App } from "./App";
import "./main.css";

render(() => <App />, document.getElementById("root") as HTMLElement);
12 changes: 12 additions & 0 deletions packages/solid/referance-app/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
pre {
display: inline;
}

nav {
display: flex;
}

nav > * {
margin-right: 1rem;
}

48 changes: 48 additions & 0 deletions packages/solid/referance-app/routes/Defer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Await, defer, useLoaderData, useAsyncError } from "remix-router-solid";
import { Suspense } from "solid-js";

const resolve = (d: string, ms: number): Promise<string> =>
new Promise((r) => setTimeout(() => r(d), ms));

const reject = (d: string, ms: number) =>
new Promise((_, r) => setTimeout(() => r(d), ms));

interface LoaderData {
critical: string;
lazy: Promise<String>;
lazyError: Promise<string>;
}

export async function deferLoader() {
return defer({
critical: await resolve("Critical Data", 500),
lazy: resolve("Lazy Data ✅", 1000),
lazyError: reject("Lazy Error 💥", 1500),
});
}
function ErrorElement() {
let error = useAsyncError();
return <p id="lazy-error">{`Error: ${error}`}</p>;
}

export const Defer = () => {
let data = useLoaderData<LoaderData>();

return (
<>
<p id="critical-data">Critical Data: {data().critical}</p>

<Suspense fallback={<p id="lazy-value">Loading data...</p>}>
<Await resolve={data().lazy}>
{(value) => <p id="lazy-value">Value: {value().toString()}</p>}
</Await>
</Suspense>

<Suspense fallback={<p id="lazy-error">Loading error...</p>}>
<Await resolve={data().lazyError} errorElement={ErrorElement}>
{() => <p>Nope!</p>}
</Await>
</Suspense>
</>
);
};
17 changes: 17 additions & 0 deletions packages/solid/referance-app/routes/Error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { LoaderFunction } from "@remix-run/router";
import { json, useLoaderData } from "remix-router-solid";

export const errorLoader: LoaderFunction = async ({ request }) => {
let isLoaderError =
new URL(request.url).searchParams.get("type") === "loader";
if (isLoaderError) {
throw new Error("Loader error!");
}
return json({});
};

export const ErrorComp = () => {
const data = useLoaderData<ReturnType<typeof errorLoader>>();

return <h2>Render Error: {data().foo.bar}; </h2>;
};
4 changes: 4 additions & 0 deletions packages/solid/referance-app/routes/Index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

export const Index = () => {
return <h2>Index Page</h2>
}
14 changes: 14 additions & 0 deletions packages/solid/referance-app/routes/Redirect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

import type { LoaderFunction } from "@remix-run/router";
import { redirect } from "remix-router-solid";
import { sleep } from "~/utils";

export const redirectLoader: LoaderFunction = async ({ request }) => {
await sleep();
let location = new URL(request.url).searchParams.get("location") || "/";
return redirect(location);
};

export const Redirect = () => {
return <h2>Shouldn't see me</h2>;
}
60 changes: 60 additions & 0 deletions packages/solid/referance-app/routes/Root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
Link,
Outlet,
useLocation,
useMatches,
useNavigate,
useNavigation,
useNavigationType,
} from "remix-router-solid";
import { For } from "solid-js";

export const Root = () => {
const links = {
Index: "/",
Parent: "/parent",
Child: "/parent/child",
Redirect: "/redirect?location=%2Fparent%2Fchild",
"Loader Error": "/error?type=loader",
"Render Error": "/error?type=render",
"Nested Loader Error": "/parent/error?type=loader",
"Nested Render Error": "/parent/error?type=render",
Defer: "/defer",
Tasks: "/tasks",
};
const hooks = {
navigationType: useNavigationType(),
location: useLocation(),
navigation: useNavigation(),
matches: useMatches(),
};

const navigate = useNavigate();
const router = navigate
return (
<>
<h1>Root Layout (solid)</h1>
<nav>
<For each={Object.entries(links)}>
{([text, href]) => {
return <Link to={href}>{text}</Link>;
}}
</For>
<button id="back" onClick={() => navigate(-1)}>
Go Back
</button>
</nav>
<For each={Object.entries(hooks)}>
{([k, v]) => {
return (
<p>
{k}():
<code id={k}>{JSON.stringify(v())}</code>
</p>
);
}}
</For>
<Outlet />
</>
);
};
Loading