This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-06-23
Channels
- # announcements (3)
- # aws (1)
- # beginners (44)
- # biff (6)
- # calva (31)
- # cider (26)
- # clerk (12)
- # clj-kondo (9)
- # clojure (17)
- # clojure-dev (18)
- # clojure-europe (13)
- # clojure-norway (45)
- # clojure-uk (4)
- # clojurescript (34)
- # datomic (54)
- # dev-tooling (14)
- # emacs (19)
- # events (7)
- # honeysql (2)
- # hyperfiddle (51)
- # lsp (34)
- # malli (24)
- # matrix (1)
- # missionary (5)
- # off-topic (27)
- # re-frame (6)
- # reagent (18)
- # releases (2)
- # sci (6)
- # shadow-cljs (88)
- # vim (9)
Hello fellas, Let’s say I wanna render some piece of React in Back-End with Shadow-CLJS (NodeJS application), what is the highly-overview steps of this in order to render it to string, so handler can send it?
normally it would be the following: compile cljs project to js, have code that runs ReactDomServer/renderToString, return the string from web endpoint handler
But I’m all in the JS environment, end-to-end. Doesn’t it help me to make things less painfull? Like, I wanna do it all in REPL, but I couldn’t even run the module since it requires React, it gives me error:
import React, { useContext, useRef, useEffect, createElement, useState, useMemo, Fragment, useCallback } from 'react';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at internalCompileFunction (node:internal/vm:73:18)
at wrapSafe (node:internal/modules/cjs/loader:1175:20)
at Module._compile (node:internal/modules/cjs/loader:1219:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
at Module.load (node:internal/modules/cjs/loader:1113:32)
at Function.Module._load (node:internal/modules/cjs/loader:960:12)
at Module.require (node:internal/modules/cjs/loader:1137:19)
at require (node:internal/modules/helpers:121:18)
at /Users/sckn/projects/closed-source/lunara/cls/.shadow-cljs/builds/lunara.cls.backend/dev/out/cljs-runtime/shadow.js.shim.module$$ionic$react.js:3:38
at global.SHADOW_IMPORT (/Users/sckn/projects/closed-source/lunara/cls/target/backend/main.js:64:44)
eehmm, that's a different question now
JS stuff is stateful, I wouldn't bother spending time to make sure it works with REPL in Node
But it has to run in NodeJS (right?), it’s just re-frame with some initialization. No interaction at all. I will cover that effectfull things later with wrappers.
Also, I already have a compiled version while I’m developing, can’t I inject that result of mine, simply?
It's not clear what your problem is about
Oh, sorry. I already have a seperate builds for my BE and FE, and they run smoothly. I need some SSR (Server-Side Rendering). When I try to require my namespace of reagent components/pages, it fails as it is up there.
Given this trivial example class component, I gather (from perusing docs and GitHub issues) that the first form is preferred:
(defn Rando []
(let [rand (r/atom (js/Math.random))]
(r/create-class {:reagent-render (fn [_] [:div @rand])
:display-name "Rando"})))
as opposed to:
(defn Rando []
(r/create-class {:constructor (fn [this props] (r/set-state this {:num (js/Math.random)
:render (fn [this] [:div (-> this r/state :num)])}))}))
Is there a strong reason to prefer one over the other, when using Form-3 components?I think I'd just use a Form-2 component for the first case. The Form-3 components are usually only needed for lower-level interop with JS or React
Yeah, in general I would do the same. I was just curious about the structure of Form 3s in general. In the Reagent GH docs it mentions that it's not a good idea to use the :render
key, and instead the :reagent-render
key should be used.
The :reagent-render
makes more sense when you want to create a class component to add lifecycle methods as opposed to using r/set-state
. I can't think of a real use case for r/set-state
today now that everyone is writing React components with hooks anyways
This is all just for my own edification anyway, but using :render
still allows for lifecycle methods, no?
I remember now that error boundaries are still implemented as classes in React and that's where r/set-state
may still be useful. In that case I'd personally prefer your first example since r/atom
is the default way of managing local state in a Reagent app. It would be less one thing to think about in a codebase if you can avoid using the setState
API altogether in favor of r/atom
Also what's interesting to me about the second example is that equivalent code in React would be an error, I think. You can't use setState
in an unmounted component, and if it's being constructed, it hasn't been mounted (I think?)
I also know quite little about React though, so maybe that's not true