SRR React With Go and Templ
Tags: react, go, backend, ssr
Published: 2024-03-01 23:06:28

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 [](https://templ.guide/media/), 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>`
}
```
After this run command`** templ generate**` so that it will generate the required go code( make sure inside static dir/folder)

6. 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,
  }
}
```
7. 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>
    )
}`
```


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
```
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} />
    );
}

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

8. 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)

}


```