5

How can I add Newsletter in PWA Magento2 ?

  • 1
    More info would be great. Your questions lacks context. What do you mean by "newsletter"? Do you mean an input field for subscription for visitors? – Akif Sep 19 at 10:30
6
+50

This code is to add newsletter in the footer, the code is based on venia concept package. change as per your need.

Here you have to create REST Api module for newsletter in Magento, there is free module available you can use that https://github.com/regento/magento2-newsletter-api

Import Newsletter in Footer: src/components/Footer/footer.js

import Newsletter from '../Newsletter';

// Add below code in render() Method
<div className={classes.newsletter}>
    <Newsletter />
</div>

Create Newsletter Component, src/components/Newsletter/index.js

export { default as Newsletter } from './newsletter';
export { default } from './container';

src/components/Newsletter/newsletter.js

import React, { Component } from 'react';
import { func, shape, string } from 'prop-types';
import defaultClasses from './newsletter.css';
import classify from 'src/classify';

import Field from '../Field';
import Button from '../Button';
import { Form } from 'informed';
import TextInput from '../TextInput';
import Icon from '../Icon';
import MailIcon from 'react-feather/dist/icons/mail';
import combine from 'src/util/combineValidators';
import { validateEmail, isRequired } from 'src/util/formValidators';

class Newsletter extends Component {
    static propTypes = {
        classes: shape({
            actions: string,
            error: string,
            lead: string,
            root: string,
            form: string,
            subscribe: string,
            signUp: string,
            signUpTitle: string,
            signUpText: string,
            inputField: string,
            signUpPolicy: string,
            successMessage: string,
            inProgressMessage: string,
            errorMessage: string
        }),
        createAccountError: shape({
            message: string
        }),
        initialValues: shape({
            email: string,
            firstName: string,
            lastName: string
        })
    };

    static defaultProps = {
        initialValues: {}
    };

    get errorMessage() {
        const { createAccountError } = this.props;

        if (createAccountError) {
            const errorIsEmpty = Object.keys(createAccountError).length === 0;
            if (!errorIsEmpty) {
                return 'An error occurred. Please try again.';
            }
        }
    }

    get initialValues() {
        const { initialValues } = this.props;
        const { email, firstName, lastName, ...rest } = initialValues;

        return {
            customer: { email, firstname: firstName, lastname: lastName },
            ...rest
        };
    }

    handleFormSubmit = async ({ email }) => {
        this.props.signUpForNewsletter({ email });
    };

    render() {
        const { errorMessage, initialValues, props } = this;
        const { classes, isError, isInProgress, isSuccess } = props;
        const mail = <Icon src={MailIcon} size={16} />;

        if (isInProgress) {
            return (
                <div className={classes.root}>
                    <p className={classes.inProgressMessage}>
                        Sending your request...
                    </p>
                </div>
            );
        }

        if (isError) {
            return (
                <div className={classes.root}>
                    <p className={classes.errorMessage}>
                        Looks like you have already signed up, Thanks!
                    </p>
                </div>
            );
        }

        if (isSuccess) {
            return (
                <div className={classes.root}>
                    <p className={classes.successMessage}>
                        Thanks for signing up for our newsletter
                    </p>
                    <small className={classes.signUpPolicy}>
                        emails are subject to our
                        <a href="/privacy-policy"> Privacy Policy</a>
                    </small>
                </div>
            );
        }

        return (
            <div className={classes.root}>
                <h2 className={classes.signUpTitle}>Let's keep in touch</h2>
                <p className={classes.signUpText}>
                    <span>
                        Stay up-to-date with our newest products and best deals
                    </span>
                </p>
                <div className={classes.inputField}>
                    <Form
                        className={classes.form}
                        initialValues={initialValues}
                        onSubmit={this.handleFormSubmit}
                    >
                        <Field label="Email" required={true}>
                            <TextInput
                                field="email"
                                autoComplete="email"
                                validate={combine([isRequired, validateEmail])}
                                validateOnBlur
                                placeholder="Email"
                                label="Email"
                                before={mail}
                            />
                        </Field>
                        <div className={classes.error}>{errorMessage}</div>
                        <div className={classes.actions}>
                            <Button type="submit" priority="high">
                                {'Submit'}
                            </Button>
                        </div>
                    </Form>
                </div>
                <small className={classes.signUpPolicy}>
                    emails are subject to our
                    <a href="/privacy-policy"> Privacy Policy</a>
                </small>
            </div>
        );
    }
}

export default classify(defaultClasses)(Newsletter);

src/components/Newsletter/container.js

import { connect } from 'src/drivers';
import Newsletter from './newsletter';
import { signUpForNewsletter } from 'src/actions/newsletter';

const mapStateToProps = ({ newsletter }) => {
    const { isInProgress, isError, isSuccess } = newsletter;

    return {
        isInProgress,
        isError,
        isSuccess
    };
};

const mapDispatchToProps = {
    signUpForNewsletter
};

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Newsletter);

src/actions/newsletter/actions.js

import { createActions } from 'redux-actions';

const prefix = 'NEWSLETTER';

const actionMap = {
    SIGN_UP_FOR_NEWSLETTER: {
        REQUEST: null,
        RECEIVE: null
    },
    NEWSLETTER_ERROR: {
        REQUEST: null,
        RECEIVE: null
    }
};

export default createActions(actionMap, { prefix });

src/actions/newsletter/asyncActions.js

import { RestApi } from '@magento/peregrine';
import actions from './actions';

const { request } = RestApi.Magento2;

export const signUpForNewsletter = ({ email }) =>
    async function thunk(...args) {
        const [dispatch] = args;

        dispatch(actions.signUpForNewsletter.request(email));

        const body = {
            email: email
        };
        const response = await request('rest/V1/newsletter/subscribe', {
            method: 'POST',
            body: JSON.stringify(body)
        });

        console.log('newsletter action response', response);
        if (response.success == true) {
            await dispatch(actions.signUpForNewsletter.receive(response));
        }

        if (response.success == false) {
            await dispatch(actions.newsletterError.receive(response));
        }
    };

src/actions/newsletter/index.js

export { default } from './actions';
export * from './asyncActions';

src/reducers/index.js

import newsletter from './newsletter';

// Add in combineReducers
export default combineReducers({
    newsletter
});

src/reducers/newsletter.js

import { handleActions } from 'redux-actions';    
import actions from '../actions/newsletter';    
export const name = 'newsletter';

const initialState = {
    isInProgress: false,
    isError: false,
    isSuccess: false
};

const reducerMap = {
    [actions.signUpForNewsletter.request]: state => {
        return {
            ...state,
            isInProgress: true,
            isError: false
        };
    },
    [actions.signUpForNewsletter.receive]: state => {
        return {
            ...state,
            isInProgress: false,
            isSuccess: true
        };
    },
    [actions.newsletterError.receive]: state => {
        return {
            ...state,
            isInProgress: false,
            isError: true
        };
    }
};

export default handleActions(reducerMap, initialState);

src/components/Newsletter/newsletter.css

Add your CSS in this file

And it works, Hope this help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.