Intro to React for HubSpot Developers

Intro to React for HubSpot Developers

Jon McLaren

Sr. Developer Advocate

Intro to React for HubSpot Developers

Developers

Intro to React for HubSpot Developers

Developers

Jon's tips for learnin' fast

  1. Dedicate time and eliminate distractions

Stop trying to multi-task, you can't. You're not a computer.

(National Library of Medicine)

Developers

Jon's tips for learnin' fast

  1. Dedicate time and eliminate distractions

"Will someone die or be seriously physically or emotionally harmed if you are to respond or address it 15 minutes from now instead of right now."

Developers

Jon's tips for learnin' fast

  1. Dedicate time and eliminate distractions

If you get anxious like you have a desire to check your phone, or see your notifications, grab something you can fidget with instead or take notes.

Developers

What's React?

  • Makes you more competitive in the job market
  • Makes you more valuable in your current job
  • Most developers have used React (according to state of JS 2022). So at some point you're probably going to touch a project that uses it.
  • React makes it easier to build complex UIs.
  • You can build on HubSpot using React! (UI Extensions, CMS Building blocks)

Why

Developers

Developers

What's React?

Why

Developers

Developers

  • There's money to be made.
  • You're likely to inherit a project that involves React in your lifetime.
  • Makes it easier to build and arguably more fun.
  • HubSpot's making it so you can build cool stuff with it.

What's React?

React JS is an open-source JavaScript library for building user interfaces, developed by Meta. React allows developers to create reusable UI components in a declarative way.

Developers

Developers

What does declarative mean?

Developers

Developers

What does declarative mean?

Developers

Developers

What does declarative mean?

// You have 1 button on a page, and an HTML output element 
// that you're displaying text in once the button is clicked.
let button = document.getElementById("myButton");
let output = document.getElementById("output");
button.addEventListener("click",(e) => {
  output.textContent="The button was clicked!"
});

Imperative

Developers

Developers

What does declarative mean?

// you have two buttons and an HTML output element you're displaying 
// the current count in - determined by increment and decrement button clicks.
let incrementButton = document.getElementById("increment");
let decrementButton = document.getElementById("decrement");
let count=0;
let output = document.getElementById("output");
incrementButton.addEventListener("click",(e) => {
  count++;
  output.textContent=`The count is at: ${count}`;
});
decrementButton.addEventListener("click",(e) => {
  count--;
  output.textContent=`The count is at: ${count}`;
});

Imperative

Developers

Developers

What does declarative mean?

import React, { useState } from "https://esm.sh/react@18.2.0";
import ReactDOM from "https://esm.sh/react-dom@18.2.0";

function App() {
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <output> The count is at {count} </output>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

Declarative

Developers

Developers

What does declarative mean?

function App() {
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <output> The count is at {count} </output>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </>
  );
}

Declarative

JSX

(JavaScript XML)

fancy HTML in JavaScript with extra rules

HTML JSX
<img src=""> <img src="" />

Developers

Developers

What does declarative mean?

function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <output> The count is at {count} </output>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
}

Declarative

JSX

(JavaScript XML)

fancy HTML in JavaScript with extra rules

HTML JSX
<img src=""> <img src="" />

Jon's tips for learnin' fast

  1. Dedicate time and eliminate distractions
  2. Relate what you know to what you're learning

Developers

Developers

Developers

What's a React component?

A React component is a reusable piece of code that describes the structure, and behavior of a part of a user interface in a web app or website. Components are abstractions that make writing and describing complicated structures in your code easier.

function MyButton({btnType,children}) {
  return (
    <button className={`btn btn-${btnType}`}>{children}</button>
  );
}

React component definition

Developers

Developers

What's a React component?

HTML Element

More similar

<button class="btn btn--primary">Save</button>
<MyButton btnType="primary">Save</MyButton>

HTML

React component

Developers

Developers

What's a React component?

HTML Element

More similar

<button class="btn btn--primary">Save</button>
<MyButton btnType="primary">Save</MyButton>

HTML

React component

Developers

Developers

What's a React component?

<button class="btn btn--primary">Save</button>
<MyButton btnType="primary">Save</MyButton>

HTML

React component

{% module "button" path="@hubspot/button" button_type="primary" button_text="Save" %}

HubSpot Module in a template

HTML Element

HubSpot Module in CMS

More similar

Developers

Developers

What's a React component?

<button class="btn btn--primary">Save</button>
<MyButton btnType="primary">Save</MyButton>

HTML

React component

{% module "button" path="@hubspot/button" button_type="primary" button_text="Save" %}

HubSpot Module in a template

HTML Element

HubSpot Module in CMS

More similar

Developers

Developers

What's a React component?

<button class="btn btn--primary">Save</button>
<MyButton btnType="primary">Save</MyButton>

HTML

React component

{% module "button" path="@hubspot/button" button_type="primary" button_text="Save" %}

HubSpot Module in a template

<my-button data-type="primary">Save</my-button>

Native Web component

HTML Element

HubSpot Module in CMS

Native Web Components

More similar

Developers

Developers

What's a React component?

<button class="btn btn--primary">Save</button>
<MyButton btnType="primary">Save</MyButton>

HTML

React component

{% module "button" path="@hubspot/button" button_type="primary" button_text="Save" %}

HubSpot Module in a template

<my-button data-type="primary">Save</my-button>

Native Web component

HTML Element

HubSpot Module in CMS

Native Web Components

More similar

Developers

Developers

What's a React component?

<MyButton btnType="primary">Save</MyButton>

React component

function MyButton({btnType,children}) {
  return (
    <button className={`btn btn-${btnType}`}>{children}</button>
  );
}

React component definition

<button class="btn btn-primary">Save</button>

HTML Output

Developers

Developers

What are Props?

<MyButton btnType="primary">Save</MyButton>

React component

function MyButton({btnType,children}) {
  return (
    <button className={`btn btn-${btnType}`}>{children}</button>
  );
}

React component definition

<button class="btn btn-primary">Save</button>

HTML Output

Developers

Developers

What's state?

<CounterButton></CounterButton>

React component

function CounterButton() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Button has been clicked {count} times
    </button>
  );
}

React component definition

<button>Button has been clicked {count} times</button>

HTML Output

Jon's tips for learnin' fast

  1. Dedicate time and eliminate distractions
  2. Relate what you know to what you're learning
  3. Integrate the thing you want to learn into the work you're already doing.

Developers

CMS JS Building Blocks Beta

Build HubSpot hosted sites with server-side React

HubSpot UI Extensions

Build custom interfaces inside of HubSpot, displaying information stored both within and outside of HubSpot in useful ways and even making it interactive.

https://jonm.d.pr/wQ74vY

gif animation of UI Extension

import React, { useState } from "react";
import {
  Form,
  Flex,
  ButtonRow,
  Button,
  Tag,
  Table,
  TableHead,
  TableHeader,
  TableBody,
  TableRow,
  TableCell,
  LoadingSpinner,
  Link,
  Select,
  EmptyState
} from "@hubspot/ui-extensions";

// Component for the table of currently assigned assets
export const AssignedAssetTable = ({assetDetails, children}) => {
  // Create a subcomponent for a row of asset details, used for the assets already associated to the contact
  // shows a loading spinner if we're loading, and empty state if nothing is assigned, or the table of assigned equipment
  if (assetDetails === null){
    // still loading, show loading display
    return <LoadingSpinner label="Loading Equipment..." showLabel={true} />
  } else if (assetDetails.length === 0){
    // no assets, show default state
    return <EmptyState title="No assigned equipment" layout="vertical" reverseOrder={true} />
  } else {
    // 
    return (
      <Table bordered={true}>
        <TableHead>
          <TableRow>
            <TableHeader width={150}></TableHeader>
            <TableHeader width={150}>Serial#</TableHeader>
            <TableHeader width={250}>Name</TableHeader>
            <TableHeader>Status</TableHeader>
          </TableRow>
        </TableHead>
        <TableBody>
          {children}
        </TableBody>
      </Table>
    )
  }
}

export const AssetDetailsRow = ( {item, props} ) => {
  // Show/hide form to update status for this specific asset
  const [isStatusFormVisible, setIsStatusFormVisible] = useState(false);
  // Show the form and make sure the form field for status always starts matching the asset's stored value
  const showStatusForm = () => {
    setChangeStatusValue(item.status ? item.status.value : "assigned")
    setIsStatusFormVisible(true);
  }
  // Hide the form
  const hideStatusForm = () => {
    setIsStatusFormVisible(false);
  }

  // Disable the form while it's processing
  const [disabledWhileWorking, setDisabledWhileWorking] = useState(false);

  // Track the value of the status form field for updating status
  const [changeStatusValue, setChangeStatusValue] = useState(item.status ? item.status.value : "assigned");

  // Build the link to the record page for the asset
  let recordUrl = `https://app.hubspot.com/contacts/${props.portalId}/record/${props.customObjectId}/${item.hs_object_id}/view/1`

  // Subcomponent for the status tag to handle the variant used based on status label
  // When the Tag is clicked, it switches to showing the form and save/cancel/remove buttons to change the status
  const EquipmentStatus = ({statusLabel}) => {
    let tagVariant ="default";

    if (statusLabel === "Out for Repairs") {
      tagVariant = "error";
    } else if (statusLabel === "Loaner") {
      tagVariant = "warning";
    } else if (statusLabel === "Assigned"){
      tagVariant = "success"
    }

    return(
      <Tag variant={tagVariant} onClick={showStatusForm}>{statusLabel}</Tag>
    )
  }

  // Handles the Save button click for updating status from its own component
  // This lets us get the asset recordId without using an input field for it
  const handleSubmitClick = () => {
    console.log("clicked save, status is:", changeStatusValue);
    setDisabledWhileWorking(true);
    props.updateAssetStatus(item.hs_object_id, changeStatusValue, resetRowState);
  }

  // Handles the remove button click, deletes the association and resets status to available
  // This lets us get the asset recordId without using an input field for it
  const sendAssetRemove = () => {
    setDisabledWhileWorking(true);
    props.removeAssetfromContact(item.hs_object_id, resetRowState);
  }
  
  const resetRowState = () =>{
    setDisabledWhileWorking(false);
    hideStatusForm();
  }

  // Renders the row in the main table
  // The status cell shows a tag component by default
  // onclick it switches to a form that lets you update the status for the record
  return(
    <TableRow key={item.hs_object_id}>
      <TableCell><Link href={recordUrl}>View Details</Link></TableCell>
      <TableCell>{item.serial_number}</TableCell>
      <TableCell>{item.name}</TableCell>
      <TableCell>
        {!isStatusFormVisible
          ? item.status ? <EquipmentStatus statusLabel={item.status.label} />: <EquipmentStatus statusLabel="None" />
          : <Form preventDefault={true}>
              <Flex direction="row" distance="extra-small">
                <Select
                  name="newStatus"
                  disabled={disabledWhileWorking}
                  options={props.statusOptions}
                  value={changeStatusValue}
                  required={true}
                  onChange={(e) => {setChangeStatusValue(e)}}
                />
                <ButtonRow>
                  <Button variant='primary' onClick={handleSubmitClick} disabled={disabledWhileWorking} >Save</Button>
                  <Button onClick={hideStatusForm} disabled={disabledWhileWorking} >Cancel</Button>
                  <Button variant='destructive' onClick={sendAssetRemove} disabled={disabledWhileWorking} >Remove</Button>
                </ButtonRow>
              </Flex>
            </Form>
        }
      </TableCell>
    </TableRow>
  )
}

HubSpot UI Extensions

Build custom interfaces inside of HubSpot, displaying information stored both within and outside of HubSpot in useful ways and even making it interactive.

https://jonm.d.pr/wQ74vY

 

Jon's tips for learnin' fast

  1. Dedicate time and eliminate distractions
  2. Relate what you know to what you're learning
  3. Integrate the thing you want to learn into the work you're already doing.
  4. Surround yourself with people who know something that you don't.

Developers

Jon's tips for learnin' fast

  1. Dedicate time and eliminate distractions
  2. Relate what you know to what you're learning
  3. Integrate the thing you want to learn into the work you're already doing.
  4. Surround yourself with people who know something that you don't.
  5. Teach someone else

Developers

Intro to React for HubSpot Developers

Copy of Intro to React for HubSpot Developers

By Jon McLaren

Copy of Intro to React for HubSpot Developers

  • 66