7

How can I add Newsletter in PWA Magento2 ?

1
  • 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
    Commented Sep 19, 2019 at 10:30

1 Answer 1

9
+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.

6
  • Hello @Ashish I installed module as per instructions. I installed in venia-ui. I am getting following error. Can u guide me on this? Uncaught TypeError: Cannot destructure property 'isInProgress' of 'newsletter' as it is undefined.
    – Arjun
    Commented Aug 19, 2020 at 4:46
  • Which pwa version you have installed? Commented Aug 19, 2020 at 12:06
  • 7.0.0 version with magento2.3.5
    – Arjun
    Commented Aug 19, 2020 at 12:21
  • Than this code will not work, you will need to modify, this is for older version. Commented Aug 20, 2020 at 5:39
  • Hello @Ashish I managed to set it in my version. Just wanted to know from where is the Newsletter email being fired? I am getting email of subscriber. But not able to get place from where they are getting fired.
    – Arjun
    Commented Aug 21, 2020 at 11:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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