dai-shi / waku

⛩️ The minimal React framework
https://waku.gg
MIT License
4.63k stars 124 forks source link

Crash with unknwon error #504

Closed himself65 closed 2 months ago

himself65 commented 8 months ago
/Users/himself65/Library/Caches/fnm_multishells/21236_1708164902479/bin/pnpm run dev

> waku-starter@0.1.0 dev /Users/himself65/Code/waku/examples/01_template
> waku dev

ready: Listening on http://localhost:3000/
rerendering...

node:internal/event_target:1088
  process.nextTick(() => { throw err; });
                           ^
 ELIFECYCLE  Command failed.

Process finished with exit code 134 (interrupted by signal 6:SIGABRT)

Step:

Modify example_01 with following changes:

// actions/index.ts
"use server"
import { RenderContext } from 'waku/server'

export const fakeDatabase = {
  userName: 'NONE',
  message: null as ReadableStream<string> | null,
}

export async function rerender(this: RenderContext) {
  console.log('rerendering...')
  fakeDatabase.userName = crypto.randomUUID()
  fakeDatabase.message = new ReadableStream({
    start(controller) {
      controller.enqueue('Hello')
      let i = 0
      setInterval(() => {
        if (i > 3) {
          controller.close()
          return
        }
        controller.enqueue(`Message ${i++}`)
      }, 10)
    }
  })
  this.rerender('')
}
// counter.tsx
'use client';

export const Counter = ({
  onClick
}: {
  onClick: () => void;
}) => {
  return (
    <section className="border-blue-400 -mx-4 mt-4 rounded border border-dashed p-4">
      <button
        onClick={() => {
          onClick()
        }}
        className="rounded-sm bg-black px-2 py-0.5 text-sm text-white"
      >
        Click
      </button>
    </section>
  );
};
import { Link } from 'waku';

import { Counter } from '../components/counter.js';
import { ReactNode } from 'react';
import { fakeDatabase, rerender } from '../actions/index.js';

async function StreamMessage (props: {
  reader: ReadableStreamDefaultReader<string>
}) {
  const { reader } = props
  const { value, done } = await reader.read()
  if (done) {
    return null
  }
  return <>
    {value}<StreamMessage reader={reader}/>
  </>
}

async function Message () {
  let children: ReactNode
  const reader = fakeDatabase.message!.getReader()
  children = StreamMessage({ reader })
  return (
    <div>
      {children}
    </div>
  )
}
export const HomePage = async () => {
  const data = await getData();
  return (
    <div>
      <title>{data.title}</title>
      <h1 className="text-4xl font-bold tracking-tight">{data.headline}</h1>
      <p>{data.body}</p>
      {fakeDatabase.userName !== 'NONE' && (
        <Message />
      )}
      <Counter onClick={rerender} />
      <Link to="/about" className="mt-4 inline-block underline">
        Learn more
      </Link>
    </div>
  );
};

const getData = async () => {
  const data = {
    title: 'Waku',
    headline: 'Waku',
    body: 'Hello world!',
  };

  return data;
};
himself65 commented 8 months ago

Follow up: I switch from stream to asyncIterator and no crash now. 👀

dai-shi commented 8 months ago

Not related to the error, but I don't see any <Suspense>. So, it goes up to the root? Doesn't it flicker?