Search code examples
reactjsreduxreact-reduxgoogle-tag-managerredux-saga

How can I wait for state to change in Redux Saga before using google tag manager?


I am trying to add google tag manager to a project where we are using Redux Saga. I'm not very familiar with either redux saga or gtm. What I am trying to do is create a gtm that looks as follows:

TagManager.dataLayer({
            dataLayer: {
                event: 'login',
                userId: user.UserID,
                locale
            }
        })

I want the event to trigger when a user logs in. The problem I have is that I can not get the UserID since the event is triggered before I have the userid and therefore shows up as undefined in gtm. The saga looks like this:

// Login user
export function* loginSaga(action) {
    yield put(actions.loginStart());

const payload = {
    username: action.username,
    password: action.password
};
try {
const response = yield axios.post('/api/auth/login', payload);
const locale = yield select(state => state.common.locale);
const user = yield select(state => state.user.user);

if (response.data.success) {
    const token = yield response.data.data.Token;
    yield cookies.set('uid', token, { path: '/' });

    yield put(actions.getUser(token));
    yield put(actions.loginSuccess(token));
    yield put(actions.closeModal());
    
        TagManager.dataLayer({
            dataLayer: {
                event: 'login',
                userId: user.UserID,
                locale
            }
        });
}

Is it possible to wait until userid is no longer undefined and THEN trigger the gtm and what would be the best practice to do so?

Let me know if you have any questions, which I assume you have. I'm pretty new to this as I mentioned earlier.

Thank you!


Solution

  • With the below lines of code, after you make axios.post, you are not storing the user details state but very soon in the next line you are trying to grab user/locale details. EDIT - Also the user needs to be obtained from the store which is updated by another ation. Therefore they are undefined.

    Solution:

    Use take which will wait the action to be completed.

    Like this

    try {
        const response = yield axios.post("/api/auth/login", payload);
        // wait until one of the success or failure action is dispatched
        yield take([ACTION_TYPES.GET_USER_DETAILS]);//provide your action type here
        const locale = yield select((state) => state.common.locale);
        const user = yield select((state) => state.user.user);
      ...