# Effectful한 프론트엔드 프레임워크 ## 컴포넌트 - `(props: P) => Effect<void, E, R | RenderScope>` - `render(eff: Effect<void, never, RenderScope>)`에 넣어서 렌더링 ## 이벤트 - 이벤트 핸들러는 이펙트를 반환할 수 있다. - 이벤트 핸들러가 반환할 이펙트의 `R`이나 `E`가 해당 핸들러가 바인딩될 요소의 E로 전이될 수 있는가? - 가능하다면 이벤트 핸들러에서 `Effect<R, E, unknown>`을 반환하도록 인터페이스를 구성하더라도 `R`, `E`를 적절하게 전이시킬 수 있음 - 근데 가능하다고 해도 이게 유저랜드 컴포넌트들이 임의의 이벤트 핸들러들에 대해 구현할 수 있을 만큼 충분히 쉬운가? - 불가능하다면.... 모든 이벤트 핸들러는 `Effect<never, never, unknown>`를 반환해야 함 ## 에러 - 컴포넌트가 반환한 `E`를 처리 - TS는 개별 JSX 요소가 반환한 `E`를 부모 요소의 `E`로 전이시킬 수 있을 만큼 똑똑한가? - 가능하다면 컴포넌트를 별도 에러 핸들링 없이도 바로 JSX에서 사용할 수 있음 - 리렌더는 어떻게? - ㅁ - 불가능하다면... `E`를 핸들링한 후에야 JSX화시킬 수 있음 ## 비동기 - Effect 특성상 비동기 렌더링 자체는 걍.... await하면 됨 - 근데 그걸 원하는 게 아님 - Suspense의 구현이 가능한가? - 먼저 fallback을 띄우고, `children` 이펙트를 fork해서 실행한 다음, 실행이 끝나면 실행 결과를 그린다 - 리렌더는 어떻게? - ㅁ ```ts= const Comp = (props) => Effect.gen(function* () { const [count, setCount] = yield* createSignal(0); const doubleCount = yield* createDerived(pipe( count, Effect.map((count) => count * 2), )); const asyncData = yield* createDerived( Effect.gen(function* () { const value = yield* doubleCount; const data = yield* Fetch(value); return data; }), ); yield* render( Suspense({ children: El.div({ children: Effect.map( asyncData, (data) => `Data: ${data}`, ), }), fallback: El.div({ children: "Loading..." }), }), ); }) ```