Простой компонент подписки с React и стилизованными компонентами
В этом коротком руководстве я покажу вам, как создать красивый компонент подписки в Gatsby и подключить его к HubSpot CRM через их API.
Если вы еще не знакомы с Гэтсби, уделите несколько минут и прочтите мою предыдущую статью.
Чтобы упростить понимание, я сначала покажу вам разметку, затем мы сделаем стиль и, в конце концов, реализуем интеграцию с HubSpot.
Давайте начнем!
Создайте компонент подписки React в Gatsby
Для компонента выше я буду использовать следующую структуру:
- Обертка, служащая контейнером для внутренних компонентов и контролирующая выравнивание формы подписки.
- Заглавный компонент
- Текстовый компонент
- Компонент формы для двух полей ввода и кнопки
Поэтому мне понадобятся отдельные файлы для каждого из этих компонентов. Итак, в папке проекта создайте для каждого компонента новый файл с именем «ComponentName.js».
Я начну с заголовка и текста:
// File Title.js import React from "react"; import styled from "styled-components"; const StyledH3 = styled.h3` font-size: 1.5rem; line-height: 2rem; font-weight: 600; color: #3F3D56; display: block; margin: ${(props) => props.isCentered ? `1rem auto` : `1rem 0`}; `; export const Heading = ({ ...props }) => { return ( <StyledH3 isCentered={props.isCentered}> {props.heading} </StyledH3> ); };
В файле Text.js
добавьте следующий код:
// File Text.js import React from "react"; import styled from "styled-components"; const StyledTextMedium = styled.p` font: inherit; font-size: 1rem; line-height: 1.25rem; margin-bottom: 1rem; color: #3F3D56; `; export const TextMedium = ({ textMedium }) => ( <StyledTextMedium>{textMedium}</StyledTextMedium> );
Затем создайте новый файл с именем Column.js
и добавьте следующий компонент:
import React from "react"; import styled from "styled-components"; export const Column = styled.div` display: flex; flex-flow: column wrap; justify-content: ${props => (props.isCentered? `center` : `flex-start`)}; align-items: ${props => (props.isCentered? `center` : `flex-start`)}; align-content: stretch; flex-basis: 1; margin: 2vw; padding: 2vw; border-radius: 2rem; ${props => (props.isFloating? `transition: all .3s cubic-bezier(.165,.84,.44,1); &:hover { transform: translateY(-0.5rem); box-shadow: 0 9px 21px 0 ${colors.colorContentLight}; } ` : ` `)}; } ` const StyledColumn100 = styled(Column)` width: calc(100% - 4rem); flex-basis: 1; margin-bottom: 1.25rem; `; export const Column100 = ({ children, ...props }) => ( <StyledColumn100 isFloating={props.isFloating} isCentered={props.isCentered} > {children} </StyledColumn100> );
Теперь мы можем определить скелет компонента Subscribe, собрав вышеперечисленные и добавив недостающие части.
В папке компонентов создайте новую подпапку для хранения компонента и добавьте два файла: Subscribe.js
для разметки и style.js
для стиля.
В файл Subscribe.js
добавьте следующий код:
import React from "react"; import { TextMedium } from "../Text.js"; import { SubscribeRow, SubscribeField, StyledSubscribe, StyledSubscribeButton, SubscribeFieldsContainer, } from "./style.js"; import { Column100 } from "../Column.js"; import { Heading } from "../Title.js"; const SubscribeButton = ({ buttonText, buttonLink }) => ( <StyledSubscribeButton to={buttonLink}> {buttonText} </StyledSubscribeButton> ); const Subscribe = () => { return ( <StyledSubscribe> <SubscribeRow> <Column100> <Heading/> <TextMedium textMedium="Receive actionable content strategy & marketing articles directly in your inbox." /> <SubscribeFieldsContainer> <SubscribeField type="email" id="email" name="email" placeholder="Your email address*" value="email" required="required" /> <SubscribeField type="text" id="firstName" name="firstName" placeholder="Your name" value="firstName" /> <SubscribeButton buttonText="Sign up" buttonLink="" /> </SubscribeFieldsContainer> </Column100> </SubscribeRow> </StyledSubscribe> ); }; export default Subscribe;
А вот стиль:
// File style.js, under /components/subscribe/ import styled from "styled-components" export const StyledSubscribe = styled.form` display: flex; flex-flow: column wrap; justify-content: center; align-items: center; align-content: center; border-radius: 2rem; background-color: ${ props => (props.isLight ? `#FFF3F7` : `#4C4C78`)}; color: #4C4C78; padding: 1.25rem; margin: ${ props => ( props.isCentered? "2vw auto" : "2vw 0")}; ` export const SubscribeRow = styled.div` margin-bottom: 1.5rem; width: 80%; display: flex; flex-flow: row wrap; justify-content: ${props => (props.isCentered ? "center" : "flex-start")}; &:last-of-type { margin-bottom: 2rem; } ` export const SubscribeField = styled.input` border: 2px solid transparent; border-radius: 2rem; flex-grow: 1; background: #FFFFFF; color: #4C4C78; padding: 1rem 2rem; font-size: 14px; margin-right: 0.75rem; margin-top: 0.75rem; &::placeholder { font-family: ${fonts.fontPrimary}; } &:hover { border: 2px solid #e32248; } &:focus { color: #e32248; border: 2px solid #e32248; outline: none; } ` export const StyledFieldsContainer = styled.div` display: flex; flex-flow: row wrap; justify-content: ${(props) => props.isCentered ? "center" : "flex-start"}; align-content: center; align-items: center; margin: 1.25rem ${(props) => (props.isCentered ? "auto" : "0")} 0; transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); a { margin-top: 0; margin-right: 2rem; } `; export const SubscribeLabel = styled.label` color: #4C4C78; font-size: 14px; ` export const SubscribeButton = styled.button` text-decoration: none; flex-grow: 1; font: inherit; font-weight: 600; border-radius: 2rem; padding: 1rem 2rem; margin-top: 0.75rem; margin-right: 0.75rem; transition: all .3s cubic-bezier(0,.89,.44,1); ` export const StyledSubscribeButton = styled(SubscribeButton)` border: none; background: linear-gradient( to right, #e32248, #A31149); color: #FFFFFF; &:hover { background: #FFFFFF; box-shadow: 0 9px 21px 0 #FFE1EC; -moz-box-shadow: 0 9px 21px 0 #FFE1EC; -webkit-box-shadow: 0 9px 21px 0 #FFE1EC; -webkit-text-fill-color: #e32248; cursor: pointer; ` export const SubscribeButtonContainer = styled(ButtonContainer)` justify-content: ${(props) => props.isCentered ? "center" : "flex-start"}; width: 100%; `;
Теперь ваш компонент готов, поэтому мы можем двигаться дальше и реализовать логику, необходимую для поддержки интеграции HubSpot.
Добавить состояние в компонент подписки React
В уже созданный компонент мы внесем несколько изменений, чтобы мы могли контролировать, что происходит, когда пользователь нажимает кнопку для отправки формы.
//File Subscribe.js import React, { useState } from "react"; import { TextMedium } from "../Text.js"; import { SubscribeRow, SubscribeField, StyledSubscribe, StyledSubscribeButton, SubscribeFieldsContainer, } from "./style.js"; import { Column100 } from "../Column.js"; import { Heading } from "../Title.js"; const SubscribeButton = ({ buttonText, buttonLink }) => ( <StyledSubscribeButton to={buttonLink}> {buttonText} </StyledSubscribeButton> ); const Subscribe = () => { const [firstName, setFirstname] = useState(""); const [email, setEmail] = useState(""); const handleSubmit = (event) => { event.preventDefault(); }; return ( <StyledSubscribe method="POST" action="/subscribe-success/" onSubmit={handleSubmit}> <SubscribeRow isCentered> <Column100 isFloating> <Heading heading="Sign up for our newsletter" / <TextMedium textMedium="Receive actionable content strategy & marketing articles directly in your inbox." /> <SubscribeFieldsContainer> <SubscribeField type="email" id="email" name="email" placeholder="Your email address*" value={email} onChange={ e => setEmail(e.target.value)} required="required" /> <SubscribeField type="text" id="firstName" name="firstName" placeholder="Your name" value={firstName} onChange={ e => setFirstname(e.target.value)} /> <SubscribeButton buttonText="Sign up" buttonLink="" /> </SubscribeFieldsContainer> </Column100> </SubscribeRow> </StyledSubscribe> ); }; export default Subscribe;
Итак, вот что я сделал:
- В форму я добавил обработчик событий
onSubmit
, который вызывает функциюhandleSubmit
. Эта функция отправит данные, которые мы собираем из полей ввода, в HubSpot API. - В полях ввода я добавил в качестве значений значения состояния
{firstName}
и{email}
. - Также я добавил обработчик событий
onChange
. Когда значение этого поля изменяется, установщикsetFirstname
изменяет значениеfirstName
в состоянии наevent.target.value
, то есть то, что пользователь добавляет в поле ввода. - Функция
handleSubmit
пока мало что делает, но я добавил методpreventDefault()
. Это препятствует тому, чтобы кнопка перенаправляла пользователя на другую страницу при отправке формы.
Теперь мы готовы к последнему шагу: интеграции HubSpot.
Интегрируйте форму HubSpot с Gatsby для компонента подписки
Сначала создайте новую учетную запись на HubSpot и выберите бесплатную опцию CRM. Когда вы закончите, перейдите на вкладку "Маркетинг" и нажмите "Формы".
Добавьте новую форму и настройте ее со следующими полями:
Затем нажмите «Опубликовать» и в открывшемся окне нажмите «Вставить код»:
Отсюда вам понадобятся portalId
и formId
.
Теперь перейдите в документацию по HubSpot API и посмотрите пример кода для отправки данных в API.
Следуя этому примеру, мы добавим приведенный ниже код в функциюhandleSubmit
function:
var xhr = new XMLHttpRequest(); var url = "https://api.hsforms.com/submissions/v3/integration/submit/portalId/formId"; // In var url above, replace portalId and formId with your values from HubSpot. // Example request JSON: var data = { submittedAt: Date.now(), fields: [ { name: "email", value: email, }, { name: "firstname", value: firstName, }, ], context: { pageUri: "subscribe-success", pageName: "Subscribe successful", }, }; var final_data = JSON.stringify(data); xhr.open("POST", url); // Sets the value of the 'Content-Type' HTTP request headers to 'application/json' xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { alert(xhr.responseText); // Returns a 200 response if the submission is successful. } else if (xhr.readyState == 4 && xhr.status == 400) { alert(xhr.responseText); // Returns a 400 error the submission is rejected. } else if (xhr.readyState == 4 && xhr.status == 403) { alert(xhr.responseText); // Returns a 403 error if the portal isn't allowed to post submissions. } else if (xhr.readyState == 4 && xhr.status == 404) { alert(xhr.responseText); //Returns a 404 error if the formGuid isn't found } }; // Sends the request xhr.send(final_data);
Вывод
Вот и все! Теперь ваша форма должна работать.
Если вы заполните его и нажмете кнопку отправки, данные будут отправлены в базу данных HubSpot, так что вы увидите всех подписчиков в CRM.
Надеюсь, вам понравился этот урок!