【问题标题】:Moving external library from Class-based to Functional Component in React在 React 中将外部库从基于类迁移到函数式组件
【发布时间】:2020-08-18 02:54:21
【问题描述】:

我将 JExcel javascript 库与 React 一起使用。该文档概述了使用组件的方法,但使用了我认为已被弃用的ReactDOM.findDOMNode()

我已经尝试将它移动到一个功能组件中,但虽然它表面上确实有效,但存在一个问题,即使用该类的 React 组件重新渲染大约 5 次......并且每次重新渲染都会导致JExcel 元素添加另一个工作表!

这是原始示例代码:

import React from "react";
import ReactDOM from "react-dom";
import jexcel from "jexcel-pro";

import "./styles.css";
import "../node_modules/jexcel-pro/dist/jexcel.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.options = props.options;
  }

  componentDidMount = function() {
    this.el = jexcel(ReactDOM.findDOMNode(this).children[0], this.options);
  };

  addRow = function() {
    this.el.insertRow();
  };

  render() {
    return (
      <div>
        <div />
        <br />
        <input
          type="button"
          value="Add new row"
          onClick={() => this.addRow()}
        />
      </div>
    );
  }
}

const options = {
    data: [
      [123, 412],
      [null, 32, 43],
      [null, null, 41, null, 54],
      [null, 123, null, 64, 23],
      [null, null, 41, 23, 123]
    ],
    minDimensions: [5, 5],
    freezeColumns: 2,
    allowComments: true,
    tableOverflow: true,
    tabs: false,
    allowCreateTabs: false,
    tableWidth: "100%"
  };

const rootElement = document.getElementById("root");
ReactDOM.render(<App options={options} />, rootElement);

这是我的更新版本,作为&lt;MyGrid /&gt; 组件:

import React, { useEffect, useRef, useState } from "react";
import ReactDOM from "react-dom";
import jexcel from "jexcel-pro";

import "./styles.css";
import "../node_modules/jexcel-pro/dist/jexcel.css";

function App(props) {
  var options = {
    data: [
      [123, 412],
      [null, 32, 43],
      [null, null, 41, null, 54],
      [null, 123, null, 64, 23],
      [null, null, 41, 23, 123]
    ],
    minDimensions: [5, 5],
    freezeColumns: 2,
    allowComments: true,
    tableOverflow: true,
    tabs: false,
    allowCreateTabs: false,
    tableWidth: "100%"
  };
  return <MyGrid options={options} />;
}

function MyGrid(props) {
  const { options } = props;
  const sheetRef = useRef(null);
  const [mySheet, setMySheet] = useState(null);

  useEffect(() => {
    setMySheet(jexcel(sheetRef.current, options));
  }, [options]);

  function addRow() {
    mySheet.insertRow();
  }

  return (
    <div>
      <div ref={sheetRef} />
      <br />
      <input type="button" value="Add new row" onClick={() => addRow()} />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

问题是数据是通过父组件中的获取来的。我怀疑是因为这个,或者可能是我对useRef 的使用不当。有更好的方法吗?

【问题讨论】:

    标签: javascript reactjs react-functional-component jexceljs react-class-based-component


    【解决方案1】:

    好的,在 Paul @JExcel 的帮助下,这是让它发挥作用的诀窍。

    import React, { useRef, useState, useEffect } from 'react'
    import jexcel from 'jexcel-pro'
    
    export default function MyGrid(props) {
      const { options } = props
      const sheetRef = useRef(null)
      const [mySheet, setMySheet] = useState(null)
    
      useEffect(() => {
        // here's the magic...
        if (!sheetRef.current.innerHTML && options.data.length > 0) {
          setMySheet( jexcel(sheetRef.current, options))
        }
        // clean-up function
        return function removeSheet() {
          sheetRef.current.remove();
        }
      }, [options])
    
      function addRow() {
        mySheet.insertRow()
      }
    
      return (
        <div>
          <div ref={sheetRef} />
          <br />
          <input type="button" value="Add new row" onClick={() => addRow()} />
        </div>
      )
    }
    
    

    为了防止多次调用外部库(本例中为 jexcel),诀窍是检查 (a) 参数是否已传递到组件中,即在本例中为 options.data.length &gt; 0,以及 (b) 我们只在我们第一次获得这些参数时调用外部库,即!sheetRef.current.innerHTML - 如果sheetRef 元素没有innerHTML,那么它还没有被启动,所以它必须是第一次。因此,对setMySheet 的调用只发生一次,并且仅在所有属性都已传入时发生。

    这是一个Sandbox 展示它的实际应用。

    【讨论】:

      猜你喜欢
      • 2020-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-11
      • 1970-01-01
      相关资源
      最近更新 更多