Skip to content
This repository was archived by the owner on Aug 27, 2018. It is now read-only.

Creating a GopherJS React app

Paul Jolly edited this page Apr 15, 2017 · 44 revisions

Initial setup

First verify that you can install the reactGen generator and it is on your PATH:

go get -u myitcv.io/react/...

# amend GOPATH and PATH to use the vendored code
export GOPATH="$(go list -f '{{.Dir}}' myitcv.io/react)/_vendor:$GOPATH"
export PATH="$(go list -f '{{.Dir}}' myitcv.io/react)/_vendor/bin:$PATH"

# amend PATH for reactGen
export PATH="$(dirname $(go list -f '{{.Target}}' myitcv.io/react/cmd/reactGen)):$PATH"

go install myitcv.io/react/cmd/reactGen

Then:

reactGen -help

should show you the options to reactGen, something like:

Usage:
        reactGen [-init <template>]
        reactGen [-gglog <log_level>] [-licenseFile <filepath>] [-core]

  -core
        indicates we are generating for a core component (only do props expansion)
  -gglog string
        log level; one of info, warning, error, fatal (default "fatal")
  -init value
        create a GopherJS React application using the specified template (see below)
  -licenseFile string
        file that contains a license header to be inserted at the top of each generated file

...

Create a minimal React app

Create yourself a new directory somewhere in your GOPATH; let's assume you call that directory helloworld. Within that directory now run:

# assuming we are in /path/to/helloworld

reactGen -init minimal

Now let's verify everything is working. Let's first confirm our app will be visible to GopherJS:

go list

should output the import path of the app we have just created. Your output will be different, but here is the output for the sample helloworld:

myitcv.io/react/examples/sites/helloworld

If this doesn't result in any errors, we're all set. So let's serve the app:

gopherjs serve

and then navigate to:

echo "http://localhost:8080/$(go list)"

(which evaluates to http://localhost:8080/myitcv.io/react/examples/sites/helloworld for the sample)

Writing components

Now that we have a good starting point, let's assume we want to create a variant on the HelloMessage component:

// hello_message.go

package hellomessage

import (
	"myitcv.io/react"
)

//go:generate reactGen

// Step 1
// Declare a type that has (at least) an anonymous embedded react.ComponentDef 
// (it can have other fields); this type must have the suffix 'Def', which corresponds to
// 'Definition'
//
type HelloMessageDef struct {
	react.ComponentDef
}

// Step 2
// Optionally declare a props type; the naming convention is *Props
//
type HelloMessageProps struct {
	Name string
}

// Step 3
// Optionally declare a state type; the naming convention is *State
//
type HelloMessageState struct {
	count int
}

// Step 4
// Declare a function to create instances of the component. If your component
// requires props to be specified, add this to the function signature. If the 
// props are optional, use a props pointer type.
//  
// This function must make a call to react.BlessElement with the value that is then
// returned.
//
// Convention is that this function is given the name of the component, HelloMessage
// in this instance. Because this component has props, we also accept these as part
// of the constructor.
//
func HelloMessage(p HelloMessageProps) *HelloMessageDef {
	res := &HelloMessageDef{}

	react.BlessElement(res, p)

	return res
}

// Step 5
// Define a Render method on the component's pointer type
//
func (r *HelloMessageDef) Render() Element {
	return Div(nil,
		S("Hello "+r.Props().Name),
	)
}

Now we run go generate (in the same directory as the component itself) to generate helper methods:

go generate

At this point you are done defining the component. Why not modify the App component that was generated in the -init step to render this component?

Always re-run go generate after making changes to a component (you might like to setup a watcher to do just this)

You can now optionally implement:

  • ComponentWillMount()
  • ComponentDidMount()
  • ComponentWillReceiveProps(...)
  • GetInitialState() ...
  • ComponentWillUnmount()

not forgetting to re-run go generate after any change.

See the various examples for instances of these methods but take note of the Gotchas

React's .js files

By default, React's production version .js files (react.min.js and react-dom.min.js) are bundled with a GopherJS build that references the myitcv.io/react package. This means you don't have to separately load React (see the Examples Showcase index.html file for example).

To bundle the development version .js files (which "includes many helpful warnings"), provide the build tag debug:

# bundle React development version .js files
gopherjs serve --tags debug

To prevent any bundling at all, use the noReactBundle build tag:

# do not bundle React
gopherjs serve --tags noReactBundle

Using this build tag obviously requires React to have been loaded separately.

Creating state trees with stateGen

Notes on stateGen to follow

Clone this wiki locally