Custom CMS React Module with business logic

Hello,
We are trying to create a custom module to use in CMS.

We need a page to collect the user information and verify it against the information on a contact. If there is such a contact, we need to display a payment page.

When the user clicks the “Verify” button, it will call a serverless function that will query HubSpot contacts. The function will return true if there is a matching contact, and a payment page will be displayed.

1- I try to test it in my local dev server by putting a simple console print for the button click event, but it doesn’t even do that.

2- When I upload the project, I don’t see the new module I created.

Here is the code for the module.

import { useState } from 'react';
import {
 ModuleFields,
 TextField,
 RichTextField,
 ImageField,
} from '@hubspot/cms-components/fields';
import { RichText } from '@hubspot/cms-components';
import logo from '../../../assets/sprocket.svg';
import styles from '../../../styles/contributions.module.css';

export function Component({ fieldValues, hublParameters }) {
 const { src, alt, width, height } = fieldValues.logo;
 const { brandColors } = hublParameters;

 const [firstName, setFirstName] = useState('');
 const [lastName, setLastName] = useState('');
 const [memberId, setMemberId] = useState('');
 const [postcode, setPostcode] = useState('');

 const verifyMember = () => {
 console.log('Verifying member...');
console.log(
 `Thank you ${firstName} ${lastName} for your submission! We will be in touch if we need to verify your member ID: ${memberId} and postcode: ${postcode}.`
 )
 }
 return (
 <div
 className={styles.wrapper}
 style={{
 backgroundColor: brandColors?.color,
 opacity: brandColors?.opacity,
 }}
 >
 <img src={src} alt={alt} width={width} height={height} />
 <h1>{fieldValues.headline}</h1>
 <div className={styles.buttons}>
 <input
 name="text"
 placeholder="First Name"
 value={firstName}
 onChange={(e) => setFirstName(e.target.value)}
 />
 </div>
 <div className={styles.buttons}>
 <input
 name="text"
 placeholder="Last Name"
 value={lastName}
 onChange={(e) => setLastName(e.target.value)}
 />
 </div>
 <div className={styles.buttons}>
 <input
 name="text"
 placeholder="Member ID"
 value={memberId}
 onChange={(e) => setMemberId(e.target.value)}
 />
 </div>
 <div className={styles.buttons}>
 <input
 name="text"
 placeholder="Postcode"
 value={postcode}
 onChange={(e) => setPostcode(e.target.value)}
 />
 </div>
 <div className={styles.buttons}>
 <button 
 onClick={verifyMember} >Verify</button>
 </div>
 </div>
 );
}

const richTextFieldDefaultValue = `
 <div>
 <div>
 <span>
 Deploy to your theme by running <pre>npm run deploy</pre> from the root directory
 </span>
 </div>
 </div>
`;

export const fields = (
 <ModuleFields>
 <ImageField
 name="logo"
 label="Logo"
 default={{ src: logo, height: 100, alt: 'HubSpot logo' }}
 resizable={true}
 />
 <TextField
 name="headline"
 label="Headline"
 default="Getting Started with CMS React"
 />
 <RichTextField
 name="gettingStarted"
 label="Getting Started"
 default={richTextFieldDefaultValue}
 />
 </ModuleFields>
);

export const meta = {
 label: 'Contributions',
};

I appreciate any help.

Hi @VSengul and welcome, it’s a pleasure to have you here!

Thank you for sharing your approach and questions around building a custom React module for HubSpot CMS on the HubSpot Community.
I’d love to put you in touch with our Top Experts: Hi @nickdeckerdevs1, @albertsg and @BelBarakat do you have suggestions to help @VSengul, please?
Have a wonderful day and thanks so much!
Bérangère

Hey @VSengul

Lets start with the first check. Did you put your function where you want to use useState in a React Island?

You need to put the interactive bits in a React Island and render that island from your module. Otherwise the component renders server-side only and never hydrates, so your click handler won’t fire in local dev or on a deployed page.