React js tsx codesandbox问题引发了跨域错误,并出现了lodash.isequal

时间:2019-09-30 13:39:40

标签: javascript reactjs qr-code codesandbox

我正在尝试以下模块代码,但它给我带来以下问题:

问题:

  

引发了跨域错误。 React无法访问   开发中的实际错误对象。看到   ... / react-crossorigin-error获取更多信息。

问题:

  

模块“ /sandbox/node_modules/@types/lodash.isequal/index”此模块   只能通过打开ECMAScript导入/导出引用   esModuleInterop标志并引用其默认export.ts(2497)

链接:Codesandbox

代码:

import * as isEqual from "lodash.isequal";
import * as qrGenerator from "qrcode-generator";
import * as React from "react";
import * as ReactDOM from "react-dom";

export interface IProps {
  value?: string;
  ecLevel?: "L" | "M" | "Q" | "H";
  enableCORS?: boolean;
  size?: number;
  quietZone?: number;
  bgColor?: string;
  fgColor?: string;
  logoImage?: string;
  logoWidth?: number;
  logoHeight?: number;
  logoOpacity?: number;
  qrStyle?: "squares" | "dots";
  style?: object;
}

export class QRCode extends React.Component<IProps, {}> {
  private canvas: React.RefObject<HTMLCanvasElement>;

  public static defaultProps: IProps = {
    value: "https://reactjs.org/",
    ecLevel: "M",
    enableCORS: false,
    size: 150,
    quietZone: 10,
    bgColor: "#FFFFFF",
    fgColor: "#000000",
    logoOpacity: 1,
    qrStyle: "squares"
  };

  private static utf16to8(str: string): string {
    let out: string = "",
      i: number,
      c: number;
    const len: number = str.length;
    for (i = 0; i < len; i++) {
      c = str.charCodeAt(i);
      if (c >= 0x0001 && c <= 0x007f) {
        out += str.charAt(i);
      } else if (c > 0x07ff) {
        out += String.fromCharCode(0xe0 | ((c >> 12) & 0x0f));
        out += String.fromCharCode(0x80 | ((c >> 6) & 0x3f));
        out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
      } else {
        out += String.fromCharCode(0xc0 | ((c >> 6) & 0x1f));
        out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
      }
    }
    return out;
  }

  private drawPositioningPattern(row, col, length, ctx) {
    const cellSize = this.props.size / length;
    for (let r = -1; r <= 7; r++) {
      if (!(row + r <= -1 || length <= row + r)) {
        for (let c = -1; c <= 7; c++) {
          if (
            (!(col + c <= -1 || length <= col + c) &&
              (0 <= r && r <= 6 && (c === 0 || c === 6))) ||
            (0 <= c && c <= 6 && (r === 0 || r === 6)) ||
            (2 <= r && r <= 4 && 2 <= c && c <= 4)
          ) {
            const w =
              Math.ceil((row + r + 1) * cellSize) -
              Math.floor((row + r) * cellSize);
            const h =
              Math.ceil((col + c + 1) * cellSize) -
              Math.floor((col + c) * cellSize);

            ctx.fillStyle = this.props.fgColor;
            ctx.fillRect(
              Math.round((row + r) * cellSize),
              Math.round((col + c) * cellSize),
              w,
              h
            );
          }
        }
      }
    }
  }

  constructor(props: IProps) {
    super(props);
    this.canvas = React.createRef();
  }

  shouldComponentUpdate(nextProps: IProps) {
    return !isEqual(this.props, nextProps);
  }

  componentDidMount() {
    this.update();
  }

  componentDidUpdate() {
    this.update();
  }

  update() {
    const {
      value,
      ecLevel,
      enableCORS,
      size,
      bgColor,
      fgColor,
      logoImage,
      logoWidth,
      logoHeight,
      logoOpacity,
      qrStyle
    } = this.props;

    const qrCode = qrGenerator(0, ecLevel);
    qrCode.addData(QRCode.utf16to8(value));
    qrCode.make();

    const canvas: HTMLCanvasElement = ReactDOM.findDOMNode(
      this.canvas.current
    ) as HTMLCanvasElement;
    const ctx: CanvasRenderingContext2D = canvas.getContext("2d");

    const length = qrCode.getModuleCount();
    const cellSize = size / length;
    const scale = window.devicePixelRatio || 1;
    canvas.height = canvas.width = size * scale;
    ctx.scale(scale, scale);

    ctx.fillStyle = bgColor;
    ctx.fillRect(0, 0, size, size);

    if (qrStyle === "dots") {
      ctx.fillStyle = fgColor;
      const radius = cellSize / 2;
      for (let row = 0; row < length; row++) {
        for (let col = 0; col < length; col++) {
          if (qrCode.isDark(row, col)) {
            ctx.beginPath();
            ctx.arc(
              Math.round(col * cellSize) + radius,
              Math.round(row * cellSize) + radius,
              (radius / 100) * 75,
              0,
              2 * Math.PI,
              false
            );
            ctx.closePath();
            ctx.fill();
          }
        }
      }

      this.drawPositioningPattern(0, 0, length, ctx);
      this.drawPositioningPattern(length - 7, 0, length, ctx);
      this.drawPositioningPattern(0, length - 7, length, ctx);
    } else {
      for (let row = 0; row < length; row++) {
        for (let col = 0; col < length; col++) {
          if (qrCode.isDark(row, col)) {
            ctx.fillStyle = fgColor;
            const w =
              Math.ceil((col + 1) * cellSize) - Math.floor(col * cellSize);
            const h =
              Math.ceil((row + 1) * cellSize) - Math.floor(row * cellSize);
            ctx.fillRect(
              Math.round(col * cellSize),
              Math.round(row * cellSize),
              w,
              h
            );
          }
        }
      }
    }

    if (logoImage) {
      const image = new Image();
      if (enableCORS) {
        image.crossOrigin = "Anonymous";
      }
      image.onload = () => {
        const dwidth = logoWidth || size * 0.2;
        const dheight = logoHeight || dwidth;
        const dx = (size - dwidth) / 2;
        const dy = (size - dheight) / 2;
        image.width = dwidth;
        image.height = dheight;
        ctx.save();
        ctx.globalAlpha = logoOpacity;
        ctx.drawImage(image, dx, dy, dwidth, dheight);
        ctx.restore();
      };
      image.src = logoImage;
    }
  }

  render() {
    return React.createElement("canvas", {
      id: "react-qrcode-logo",
      height: this.props.size,
      width: this.props.size,
      style: {
        height: this.props.size + "px",
        width: this.props.size + "px",
        padding: this.props.quietZone + "px",
        background: this.props.bgColor
      },
      ref: this.canvas
    });
  }
}

1 个答案:

答案 0 :(得分:0)

我在您的沙箱中仅看到跨域抛出的错误。我已经在codeandbox中多次看到这种跨域错误,我相信这是因为它在iframe中运行,并且据我所知是无害的。

我认为仅使用默认导入就可以解决您的第二个错误,这对您在沙箱中的操作来说是一样的。

import isEqual from "lodash.isequal";