Обновление до React 16 findDOMNode перестает работать
Я только что попытался обновить React до версии 16. К сожалению, React Toolbox, который я использую в качестве библиотеки пользовательского интерфейса, еще не адаптирован для этого.
Я взял на себя квест, но наткнулся на то, что я не мог найти решение
React Toolbox использует React.finDOMNode для выполнения некоторых вычислений позиционирования. После обновления до React 16 findDomNode теперь всегда возвращает ноль, и React Toolbox перестает работать должным образом.
Я пытался изолировать дело, но мне не удалось. В Isolation 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, например, в компоненте Ripple в строке 88, он всегда возвращает ноль.
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,
};
}
В большинстве случаев мне удалось заменить findDOMNode ссылками, но не в этом случае (ссылка в Ripple будет ссылаться на компонент React, а не на элемент), решив, что с помощью React.finDOMNode также возвращается значение null.
- Что-то изменилось в React.findDOMNode, чтобы он больше не работал, как в прошлом?
- Как я могу принять это изменение во внимание и сделать React TOolbox совместимым с React 16.
- Есть ли у вас какие-либо идеи исправить это?
С наилучшими пожеланиями Тобиас
1 ответ
Я столкнулся с той же проблемой. Я не достаточно знаком с внутренностями React DOM, чтобы точно знать, что изменилось, и если это просто ошибка пользователя с нашей стороны, но после небольшой проверки я придумал эту функцию, которая возвращает правильный узел DOM. NB: здесь я использую приватные переменные, так что используйте на свой страх и риск.
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
}
}
Код довольно прост; вы спускаетесь по дереву узлов Fiber, пока stateNode
является элементом DOM или у вас закончились дети.