1

我正在尝试创建一个<Drift>安装 Drift 聊天服务的组件:

漂移.js

import React, { useEffect, useState } from 'react'

export default function Drift (props) {
  const [drift, setDrift] = useState(undefined)

  // Evaluate the drift script once
  useEffect(() => {
    const script = document.getElementById('drift-script').innerHTML
    window.eval(script)
  }, [])

  // Poll for drift availability
  useEffect(() => {
    const poller = setInterval(() => {

      if (window.drift) {
        setDrift(window.drift)
        clearInterval(poller)

        console.log('setDrift(fn) called')
      }
    }, 500)

    return () => clearInterval(poller)
  }, [])

  // Configure the drift widget once
  useEffect(() => {
    console.log('drift depended effect triggered:')
    console.log(typeof drift)

    if (drift) {
      console.log('drift is defined')

      drift.config({
        messages: {
          welcomeMessage: 'Your code is being generated!'
        }
      })

      drift.on('ready', function (api) {
        console.log('drift ready')

        api.widget.hide()

        api.widget.show()
        api.showWelcomeMessage()
      })
    }
    else {
      console.log('drift is undefined')
    }
  }, [drift])

  return (
    <div>
      <script
        id="drift-script"
        dangerouslySetInnerHTML={{
          __html: `
          "use strict";

          !function() {
            var t = window.driftt = window.drift = window.driftt || [];
            if (!t.init) {
              if (t.invoked) return void (window.console && console.error && console.error("Drift snippet included twice."));
              t.invoked = !0, t.methods = [ "identify", "config", "track", "reset", "debug", "show", "ping", "page", "hide", "off", "on" ], 
              t.factory = function(e) {
                return function() {
                  var n = Array.prototype.slice.call(arguments);
                  return n.unshift(e), t.push(n), t;
                };
              }, t.methods.forEach(function(e) {
                t[e] = t.factory(e);
              }), t.load = function(t) {
                var e = 3e5, n = Math.ceil(new Date() / e) * e, o = document.createElement("script");
                o.type = "text/javascript", o.async = !0, o.crossorigin = "anonymous", o.src = "https://js.driftt.com/include/" + n + "/" + t + ".js";
                var i = document.getElementsByTagName("script")[0];
                i.parentNode.insertBefore(o, i);
              };
            }
          }();
          drift.SNIPPET_VERSION = '0.3.1';

          drift.load('DRIFT_ID');
          `
        }}
      />

      { props.children }
    </div>
  )
}

这个想法是一旦window.drift定义效果就会运行。但是,效果只运行一次——当 window.drift 未定义时。

完整的日志是:

drift depended effect triggered:
Drift.js:30 undefined
Drift.js:51 drift is undefined
Drift.js:20 setDrift(fn) called

如何创建对 window.drift 的引用,该引用会导致效果在定义后执行?

4

2 回答 2

1

如果可以导入库,那将是可取的:

import Drift from 'drift'

如果没有,我建议运行与 React 无关的命令式代码index.js

import ReactDOM from 'react-dom'
...
!function() {
  var t = window.driftt = window.drift = window.driftt || [];
  ...
ReactDOM.render(...)

或者从一个单独的文件中执行脚本index.htmlpublic如果使用 create-react-app,则在文件夹中):

<body>
  <div id='root'>
  <script src="drift.js"></script>
</body>
于 2019-06-29T13:41:27.007 回答
1

您可以将 Drift 客户端作为脚本添加到 head 标签中。

工作示例

编辑 kind-shape-1wus8


为了让它工作,将由drift给出的脚本的内容作为文本添加到文件中。useEffect然后,通过创建脚本标签将其作为脚本加载。

useEffect(() => {
  const script = document.createElement("script");
  script.setAttribute("type", "text/javascript");
  script.innerHTML = drift;
  document.head.appendChild(script);
  return () => script.parentNode.removeChild(script);
}, []);

此外,如果您希望它在您的应用程序中可用,您可以将其作为内联脚本标签添加到您的模板索引 html 文件中,该文件由 webpack 使用。

于 2019-06-29T03:27:38.143 回答