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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redirect doesn't early exit component when loading from browser address bar #1457

Open
2 tasks done
aquaductape opened this issue Apr 23, 2024 · 3 comments
Open
2 tasks done
Labels
bug Something isn't working

Comments

@aquaductape
Copy link

aquaductape commented Apr 23, 2024

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 馃槸

When redirecting inside async server function call, the rest of the component still continue to run inside the server.

routes/admin.tsx

import { cache, createAsync, redirect } from "@solidjs/router";

const isAuthorized = false;

const getUser = cache(async () => {
  "use server";

  console.log("getUser: before redirect"); // logs
  if (!isAuthorized) {
    throw redirect("/about");
  }
  console.log("getUser: after redirect"); // doesn't log
  return {
    name: "John",
    age: 42,
  };
}, "getUser");

const Admin = () => {
  const res = createAsync(() => getUser());

  // server does unnecessary work here when redirecting
  console.log("Admin component"); // logs even after redirect, logs twice as well

  return (
    <div>
      <h1>admin</h1>
      <p>{res()?.name}</p>
    </div>
  );
};

Logs in server:

getUser: before redirect
Admin component
Admin component

Expected behavior 馃

Basically for redirecting to exit early in the component execution, like how NextJS 14 works.

NextJS 14
app/admin/page.tsx

import { redirect } from 'next/navigation';

const isAuthorized = false;

const getUser = async () => {
  'use server';

  console.log('getUser: before redirect'); // logs
  if (!isAuthorized) {
    redirect('/about');
  }
  console.log('getUser: after redirect'); // doesn't log
  return {
    name: 'John',
    age: 42,
  };
};

const Admin = async () => {
  const res = await getUser();

  // server skips rest when redirecting
  console.log('Admin component'); // doesn't log

  return (
    <div>
      <h1>admin</h1>
      <p>{res?.name}</p>
    </div>
  );
};

Logs in server:

getUser: before redirect

Steps to reproduce 馃暪

Steps:

  1. clone https://github.com/aquaductape/solid-start-redirect-test
  2. enter http://localhost:3000/admin in browser address bar
  3. redirects to /about
  4. see terminal logs

Context 馃敠

No response

Your environment 馃寧

System:
  OS: macOS 14.4.1 (23E224)
  Chip: Apple M1 Pro
Binaries:
  Node: v18.17.1
  npm: 10.1.0
npmPackages:
  solid-start: ^1.0.0-rc.0
@aquaductape aquaductape added the bug Something isn't working label Apr 23, 2024
@aquaductape
Copy link
Author

aquaductape commented Apr 23, 2024

Note 1

When navigating to admin page via clicking Admin anchor tag,
Screenshot 2024-04-22 at 10 32 11鈥疨M

it works to my expectation, early exits component after redirect like NextJS

Note 2

If I remove the optional chain operator on res()?.name that's rendered inside Admin component jsx, it crashes on client because res() returns undefined. But if you navigate to admin page via browser addressbar, the crash is ignored (logs error in terminal in dev mode).

const Admin = () => {
  const res = createAsync(() => getUser());

  // server does unnecessary work here when redirecting
  console.log("Admin component"); // logs even after redirect

  return (
    <div>
      <h1>admin</h1>
      <p>{res().name}</p>
    </div>
  );
};

@aquaductape aquaductape changed the title Redirect is ignored when loading from address URL bar Redirect doesn't early exit component when loading from address URL bar Apr 23, 2024
@aquaductape aquaductape changed the title Redirect doesn't early exit component when loading from address URL bar Redirect doesn't early exit component when loading from browser address bar Apr 23, 2024
@ryansolid
Copy link
Member

ryansolid commented Apr 23, 2024

This is by design to a certain degree. Our Async isn't blocking until where you read from the resource, not where you declare it. This avoids waterfalls that Next cannot. Similarly our resources don't throw and can be undefined. Again to be non-blocking. We are exploring space of doing blocking along the reactive graph rather than the components in Solid 2.0. But the short of this is Solid does not work like React and we need to work on our documentation.

The error behavior inconsistency on SSR + Hydration vs navigation is interesting. I'm gathering doesn't cause the server to error for some reason and then it gets skipped during hydration. That is probably worth further examination.

@apatrida
Copy link

You can avoid the rendering part by not showing the component until the resource is ready.

Add Show as below

const Admin = async () => {
  const res = await getUser();

  createEffect(()=>{
       if (res()) {
           // won't log as by the time the component loads and redirects this won't get here
           console.log('Client - Admin component'); 
       }
  });
  
  // will log, as the resource hasn't loaded to do the redirect yet
  console.log('Client and Server - Admin component'); 

  return (
    <Show when{res()}>   
	    <div>
	      <h1>admin</h1>
	      <p>{res?.name}</p>
	    </div>
	</Show>
  );
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants