DEV Community

are_you_garabage_or_am_i
are_you_garabage_or_am_i

Posted on • Updated on

SRR React With Go and Templ

Recently I came across some problem where I need to do a server side rendering, I thought of using HTMX with templ but I didn't, I go for react with templ, Not because React is better choice, btw I don't know how to center a div(terrible at frontend thingy)

So I am here to share the process and It's already on the templ documentation , but i have some issue on that I change here and there.

  1. Install temp go install github.com/a-h/templ/cmd/templ@latest

  2. add go get github.com/a-h/templ to your project

  3. now make a dir/folder inside your go project e.g react-integration

  4. cd react-integration and make two dir/folder static(where your templ and templ geneated go file should be) and another one react()

  5. inside static create a page.tmpl

make sure you have data to pass if you need the data to render,

package static
   import(
      "github.com/username/myrepo/types"
  )
   */
script renderIndex(bp types.BillingPlan) {
    // Use the renderIndex function from the Reactbundle
    bundle.renderIndex()
}

templ Index(bp types.BillingPlan) {
    <div id="index"></div>  
    // in templ you this to call a templ component or script  
    @renderIndex(bp)
}


templ Page(bp types.BillingPlan) {
`<html>
    <head>
        <title>React integration</title>
            <link rel="stylesheet" href="static/index.css" 
            </link>
    </head>
    <body>
        <div id="react-header"></div>
        <div id="react-content"></div>
        <div>
        </div>  
           // this index.js will be generate by es build 
        <script src="static/index.js"</script>
            @Index(c, fs) 
    </body>
</html>`
}
Enter fullscreen mode Exit fullscreen mode

After this run command** templ generate** so that it will generate the required go code( make sure inside static dir/folder)

  1. inside react do npm init -y make this files tsconfig.json and install necessary package(ts, esbuild, react, react-dom) or copy pasta this { "name": "react-integration", "version": "1.0.0", "description": "", "main": "index.ts", "author": "", "license": "ISC", "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@types/react-dom": "^18.2.18", "esbuild": "0.20.1", "npm-run-all": "^4.1.5", "typescript": "^5.3.3" } }

we are using tsx for bundle so we use react for jsx

{
  "compilerOptions": {
      "jsx": "react", 
      "lib": ["ESNext", "DOM"],
      "esModuleInterop": true,
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. create your required files for me i will create components.tsx , index.tsx and app.tsx
components.tsx
`import React from "react";

export function Component(props:any){
    return(
    <div>
       <h3 onClick={()=> console.log(data)>Click Me</h3>
    </div>
    )
}`
Enter fullscreen mode Exit fullscreen mode

app.tsx

import  React, { useEffect, useRef, useState } from 'react';
import { Component } from "./components"

const App = (props : any) =>{
// do whatever you want
 return(
   <Component billingPlan={props}/>
 )
}
export default App
Enter fullscreen mode Exit fullscreen mode

index.tsx

import ReactDOM from 'react-dom/client';
import React from 'react';
import App from './app';

export function renderIndex(content:any){
    const root = ReactDOM.createRoot(document.getElementById('index') as HTMLElement);
    root.render(
       <App content={content} />
    );
}

Enter fullscreen mode Exit fullscreen mode

generate the index.js bundle using this command ./node_modules/.bin/esbuild --bundle index.tsx --outdir=../static --minify --global-name=bundle

  1. Now we have to serve I like to use echo framework
package main

import(
    "github.com/labstack/echo/v4"
    "github.com/username/types"
    "net/http"

)

func main(){

  e := echo.New() 

  // middleware for serving static file
  e.Static("/static", "./integration-react/static")

  // routes 
  e.Any("/shit",echo.HandlerFunc(func(c echo.Context) error {
   // call the template component in the static
   templComp := static.Page(types.BillingPlan{})
   Render(c, http.StatusOK, templComp) 
  }))

  s := http.Server{
       Addr:        ":8080",
       Handler:     e,
   }
  if err := s.ListenAndServe(); err != http.ErrServerClosed {
    log.Fatal(err)
  }

}

// this is the echo integration with templ code
func Render(ctx echo.Context, statusCode int, tc templ.Component) error {

    ctx.Response().Writer.WriteHeader(statusCode)
    ctx.Response().Header().Set(echo.HeaderContentType, 
                                     echo.MIMETextHTML)
    return tc.Render(ctx.Request().Context(), 
                             ctx.Response().Writer)

}


Enter fullscreen mode Exit fullscreen mode

Top comments (0)