更新到React 16 findDOMNode停止工作

时间:2018-01-02 13:42:21

标签: reactjs react-toolbox

我只是尝试将React更新到版本16.不幸的是,我用作UI库的React Toolbox尚未适应。

我接受了这个任务但偶然发现了一些我无法找到解决方案的事情

React Toolbox使用React.finDOMNode进行一些定位计算。升级到React 16后,findDomNode现在总是返回null并且React Toolbox停止正常工作。

我试图隔离案件,但我失败了。在隔离中,React.findDOMNode始终返回正确的节点。

隔离代码:

import PropTypes from 'prop-types';
import React, {Component} from 'React';
import ReactDOM from 'react-dom';
//import get from 'lodash/get';
//import classNames from 'classnames';
//import css from './css.css';

const yeah = () => {
    class YoloComp extends Component {
        render = () => (<div {...this.props} >YOLO</div>)
    }

    return YoloComp;
};

let Yeah = yeah();

export default class Test extends Component {
    static propTypes = {};

    click = () => {
        this.foo();
    };

    foo = () => {
        console.log('ref', this.node);
        console.log('dom this', ReactDOM.findDOMNode(this));
        console.log('dom node', ReactDOM.findDOMNode(this.node));
    };

    componentDidMount() {
        setTimeout(() => {
            this.foo();
        });
    }

    render() {
        return (

            <Yeah ref={(r) => this.node = r} onClick={this.click}/>
        );
    }
}

在React Toolbox中,例如在第88行的Ripple Component中,它总是返回null。

getDescriptor(x, y) {
        const { left, top, height, width } = ReactDOM.findDOMNode(this).getBoundingClientRect();
        const { rippleCentered: centered, rippleSpread: spread } = this.props;
        return {
          left: centered ? 0 : x - left - (width / 2),
          top: centered ? 0 : y - top - (height / 2),
          width: width * spread,
        };
      }

在大多数情况下,我能够用refs替换findDOMNode,但在这种情况下不能(Ripple中的ref将引用React组件而不是Element),使用React解析它.finDOMNode也返回null。

  1. React.findDOMNode中是否有任何更改,以至于它不再像过去那样工作了?
  2. 如何将此更改考虑在内并使React TOolbox与React 16兼容。
  3. 你有解决这个问题的想法吗?
  4. 祝你好运 托拜厄斯

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题。我不熟悉React DOM内部,以确切地知道改变了什么,如果这只是我们的用户错误,但稍微检查一下,我想出了这个返回正确DOM节点的函数。注意:我在这里使用私有变量,因此使用风险自负。

function dangerouslyFindDOMNode(_reactElement){
  try {
    console.warn("'dangerouslyFindDOMNode' is liable to break, and often")
    let fiberNode = _reactElement._reactInternalFiber
    while (fiberNode && !(fiberNode.stateNode instanceof Element)) {
      fiberNode = fiberNode.child
    }
    return fiberNode ? fiberNode.stateNode : null
  } catch(e){
    console.error(e)
    return null
  }
}

代码很简单;你下降光纤节点树,直到stateNode是一个DOM元素,或者你的孩子用完了。