narkq / react-yandex-metrika

React component for Yandex.Metrika
128 stars 25 forks source link

Ошибка после добавления ym #25

Open Aleks-developer opened 5 years ago

Aleks-developer commented 5 years ago

Здравствуйте. Делаю все по инструкции, после добавления ym на событие onClick вылазит следующая ошибка: TypeError: Cannot read property 'forEach' of undefined. В чем может быть проблема?

JustFly1984 commented 5 years ago

@Aleks-developer Я поковырялся в коде, и нашёл решение - инициализатор надо импортировать как функцию в index.js - и запускать с 3 агрументами

import YMInitializer from 'react-yandex-metrika/lib/init'

YMInitializer([yandexMetrikaKey], { webvisor: true }, '2')

самое главное запускать эту функцию до самого кода реакта

а дальше в онкликах и роутах можно использовать ym как в документации

LeeTwelve commented 5 years ago

@JustFly1984 Так не работает, так как даже нет никакой сетевой активности

JustFly1984 commented 5 years ago

Well, at the end I wrote my own script:

const isBrowser = typeof document !== 'undefined'

export const injectScript = ({ url, id, onSuccess, onError }) => {
  if (isBrowser) {
    return new Promise((resolve, reject) => {
      const prevScript = document.getElementById(id)

      if (!prevScript) {
        const script = document.createElement('script')

        script.type = 'text/javascript'
        script.src = url
        script.id = id
        script.async = true
        script.onload = () => {
          resolve(onSuccess())
        }
        script.onerror = (e) => {
          reject(onError(e))
        }
        document.head.appendChild(script)
      } else {
        resolve(onSuccess())
      }
    })
  } else {
    onError()
  }
}

export const init = id => {
  try {
    window[`yaCounter${id}`] = new Ya['Metrika2']({
      id,
      clickmap: true,
      trackLinks: true,
      accurateTrackBounce: true,
      webvisor: true
    })
  } catch (err) {
    console.warn(err)
  }
}

export const ym = (id, methodName, ...args) => {
  if (
    isBrowser &&
    typeof window[`yaCounter${id}`] !== 'undefined'
  ) {
    window[`yaCounter${id}`][methodName](...args)
  }
}

export const injectYm = id => {
  injectScript({
    id,
    url: 'https://mc.yandex.ru/metrika/tag.js',
    onSuccess: () => {
      init(id)

      ym(id, 'hit', window.location.pathname)

      console.log('yandex metrika initialized')
    },
    onError: () => {
      console.error('Yandex metrika if failed')
    }
  })
}

You need to injectYm('546346) before ReactDOM.render, and use ym(546346, 'hit', window.location.pathname)

ryskin commented 5 years ago

Still no news?

hdkeeper commented 5 years ago

Отправил PR, который должен исправить этот баг. Примите, пожалуйста.

baitun commented 5 years ago

Ошибка возникает, если в коде ym() вызывается раньше, чем примонтировался <YMInitializer/>.

hdkeeper commented 5 years ago

Да, так и есть. Опишу свой сценарий использования более подробно.

У меня YMInitializer подключается как в документации:

<YMInitializer accounts={[YANDEX_METRIKA_ID]} options={{ defer: true }} />

а ym() вызывается в коде middleware/saga при смене пути. Когда загружается первая страница, происходит первое событие LOCATION_CHANGE. Но в этот момент YMInitializer ещё не смонтирован.

Я нашёл ещё один способ обойти этот баг. Он не требует внесения изменений в библиотеку, и события не должны теряться.

import {
    call, all, takeLatest, delay
} from 'redux-saga/effects';

import { LOCATION_CHANGE } from 'connected-react-router';
import ym from 'react-yandex-metrika';

function* locationChangeSaga({ payload }) {
    try {
        // Событие роутера LOCATION_CHANGE прилетает раньше, чем успевает отработать YMInitializer.
        // Поэтому для hit-событий добавляем небольшую задержку.
        yield delay(100);

        yield call(ym, 'hit', payload.location.pathname);
    } catch (error) {
        logServerError(error);
    }
}

export default function* rootSaga() {
    yield all([
        yield takeLatest(LOCATION_CHANGE, locationChangeSaga)
    ]);
}
NairiAreg commented 4 years ago

У меня никак не работает JavaScript событие, <YMInitializer accounts={[66898726]} options={{webvisor: true}} version="2" />

ym('hit', '/'); ym(66898726,'reachGoal','arhitektor-form');

что интересно это то что в дебаге hit видно в консоле а вот reachGoal ну никак нет метрика тоже работает только цели никак не отоброжаются