rogeramitchell / midwest-dreamin-17-building-react-apps

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Building React Apps in Salesforce

Roger Mitchell

Cofounder, Bluestone Labs

@RogerMitchell

Sponsors!

sponsors.png

Agenda

  • What is React?
  • Why (not) use React?
  • React + Salesforce + You
  • Advanced Patterns
  • Demo!
  • Questions & Answers

Speaker Note: BEFORE DIVING INTO MATERIAL:

  • Ask by show of hands: who is familiar with a “Single Page App”?
  • Ask by show of hands: who has written JavaScript before?
  • Ask by show of hands: who is familiar with ReactJS?

What is React?

coder.gif

What is React?

  • JavaScript library created + maintained by Facebook
  • Built for creating UIs
  • Embraces MV* to as View layer to your Model’s data
  • Efficiently handles updates to browser’s DOM
  • Mixes HTML and CSS into JS as “JSX”

What is React?

  • Components are composed to create an app
  • Data are stored as “state” at highest level necessary
  • Component state, functions are passed as “props”
  • Use “props” to render, execute functions
  • Only can modify state; rest of app inherits as props
  • Uses “virtual DOM” to identify diffs with the DOM

Why (not) use React?

Where's my Safe Harbor slide?

Why use React?

  • Handles simple CRUD apps, data heavy pages
  • Large community of web devs + designers
  • npm install any packages to aid development
  • Augment your CRM dev team with your website’s dev team or agency
  • Drop into a Visualforce page now, Lightning Component or App later
  • Keep UI the same when switching out the backend

Why not use React?

  • React is not maintained by Salesforce, bugs happen
  • Lack of “metadata awareness” when logic exists in JS
  • Existing team has learning curve
  • Hiring "framework of the day" devs is more difficult
  • Large amount of local tooling is (really) required
  • Requires using third party components available on npm (or building your own)

React + Salesforce + You

A journey into tooling, and treating the platform like an API.

Thinking in React

  • Sketch the UI on paper, or take a screenshot of a prototype
  • Identify areas that can act as components
    • Do not be afraid to nest components
    • If you can abstract reasonably, do so
  • Leverage others’ work to define components (e.g. SLDS)

Annotate Your Prototypes

annotate-your-prototypes.png

Metadata Model

  • Apex Controller facilitates queries, DML via RemoteAction methods
  • Visualforce Page acts as container in which to mount the React app
  • Static Resource contains bundled components, helpers, third-party modules, etc
  • Looks similar to importing JS for a jQuery project

Visualforce Page Markup

<apex:page standardStylesheets="false" showHeader="false"
	showChat="false" sidebar="false" docType="html-5.0"
	controller="AccountManagementController"
	applyBodyTag="false">
<body>
	<link rel="stylesheet" type="text/css"
		href="{!URLFOR($Resource.SLDS,
		'assets/styles/salesforce-lightning-design-system-vf.min.css')}" />
	<div id="app" class="react-vf"></div>
	<script type="text/javascript"
		src="{!URLFOR($Resource.AccountManagement, 'js/app.js')}"></script>
</body>
</apex:page>

Development Tooling

  • Use Node.js and npm to set up local project
  • Install React to create components, establish state
  • Install ReactDOM to mount the app into the browser’s DOM
  • Use React Dev Tools for troubleshooting
  • Optionally...
    • Install Babel to transpile ES2015/ES6 for older browsers
    • Install Webpack to bundle code into single asset files

Node Project's package.json

{
  "name": "dynamic-page-mapping",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.22.1",
    "babel-loader": "^6.2.10",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-react": "^6.22.0",
    "css-loader": "^0.26.1",
    "style-loader": "^0.13.1",
    "webpack": "^2.2.1",
    "webpack-dev-server": "^2.4.5"
  },
  "dependencies": {
    "react": "^15.4.2",
    "react-dom": "^15.4.2"
  }
}

Babel's Config File

{ "presets": [ "react", "es2015" ] }

Webpack's Config File

let path = require('path');

module.exports = {
	entry: './dev/js/App.js',
	output: {
		path: path.resolve(__dirname,
			'./resource-bundles/AccountManagement.resource/js'),
		filename: 'app.js'
	},
	module: {
		loaders: [
			{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' },
			{ test: /\.css$/, loader: "style-loader!css-loader" }
		]
	}
};

React Dev Tools

react-dev-tools-1.png

React Dev Tools

react-dev-tools-2.png

Advanced Patterns

Because JS has advanced (too) much in the last few years.

Wrapper Class for State

  • Use single request to retrieve a “StateBundle”
  • Deconstruct StateBundle into different objects/collections
  • Call setState() to assign data to React’s state
  • Return StateBundle back after DML, repeat deconstruction

Constructing StateBundle in Apex

global class StateBundle
{
	public List<Resource> resources;
	public List<Card> cards;
	public String recordTypeName;
}

Parsing StateBundle in Client Side JS

export function getInitialState(recordId, context) {
	Visualforce.remoting.Manager.invokeAction(
		'T1ResourceVisualizationController.getInitialState',
		recordId, true,
		function(result, event) {
			if(event.statusCode === 200) {
				// decompose result
				let Cards = result.cards;
				let ResourceMap = buildResourceMap(result.resources);
				let FilterMap = buildFilterCounts(Cards, context.state.SelectedView);

				// get default filters
				let Filters = defaultFilters;

				// set state 
				context.setState({
					RecordTypeName: result.recordTypeName,
					Cards,
					ResourceMap,
					FilterMap,
					Filters
				});
			} else {
				console.error('Houston, we have a problem! 🌮');
			}
		}
	);
}

Redirecting to localhost

  • Serve app to localhost using webpack-dev-server
  • Redirect browser requests to localhost using Requestly
  • Prevent deploying static resource bundle
  • Speed up your development cycles

Redirecting to localhost

Start webpack-dev-server via Terminal...

webpack-dev-server --content-base 
resource-bundles/YourResourceName.resource --https

Using Requestly, replace...

/https.*\/resource\/[0-9]+\/YourResourceName/ig

with...

https://localhost:8080

Metadata Driven Rendering

  • Abstract app further with smaller components
  • Use Field Sets and Custom Metadata Types to allow non-developers to control UI features
  • Describe fields to support i18n and custom translations
  • Leverage FieldSetReactor as utility to compose server-side details, serve with app’s StateBundle (i.e. app data)

Use Field Sets with Field Set Reactor

@RemoteAction
public static List<FieldSetReactor.FieldDetails> getFields(
	String fieldSetName,
	String objectName)
{
	return FieldSetReactor.getFieldDetails(fieldSetName, objectName);
}

Field Details from Field Set Reactor

field-set-details.png

Demo Time!

Awww yeah...

demo.gif

Speaker Note:

  • Changes to field set updates the UI
  • Changes to labels updates the UI
  • React Dev Tools for debugging + viewing metadata abstraction
  • Requestly for efficient development

Helpful Resources

PEP UP TECH!

pepuptech.png

Questions?

questions.gif

Thanks y'all!

Roger Mitchell

Cofounder, Bluestone Labs

@RogerMitchell

About

License:MIT License


Languages

Language:CSS 47.1%Language:JavaScript 44.7%Language:HTML 8.3%