tru*_*ktr 24 javascript reactjs react-ref
正常情况下,有了props,我们就可以写
componentDidUpdate(oldProps) {
if (oldProps.foo !== this.props.foo) {
console.log('foo prop changed')
}
}
Run Code Online (Sandbox Code Playgroud)
为了检测道具的变化。
但是如果我们使用React.createRef(),我们如何检测 ref 何时更改为新组件或 DOM 元素?React 文档并没有真正提及任何内容。
铁,
class Foo extends React.Component {
someRef = React.createRef()
componentDidUpdate(oldProps) {
const refChanged = /* What do we put here? */
if (refChanged) {
console.log('new ref value:', this.someRef.current)
}
}
render() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
我们是否应该自己实现某种旧价值的东西?
铁,
class Foo extends React.Component {
someRef = React.createRef()
oldRef = {}
componentDidMount() {
this.oldRef.current = this.someRef.current
}
componentDidUpdate(oldProps) {
const refChanged = this.oldRef.current !== this.someRef.current
if (refChanged) {
console.log('new ref value:', this.someRef.current)
this.oldRef.current = this.someRef.current
}
}
render() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
这是我们应该做的吗?我原以为 React 会为此添加一些简单的功能。
for*_*d04 42
React 文档推荐使用回调引用来检测ref值的变化。
export function Comp() {
const onRefChange = useCallback(node => {
if (node === null) {
// DOM node referenced by ref has been unmounted
} else {
// DOM node referenced by ref has changed and exists
}
}, []); // adjust deps
return <h1 ref={onRefChange}>Hey</h1>;
}
Run Code Online (Sandbox Code Playgroud)
useCallback用于防止使用null和 元素重复调用ref 回调。
您可以通过使用以下命令存储当前 DOM 节点来触发重新渲染useState:
const [domNode, setDomNode] = useState(null);
const onRefChange = useCallback(node => {
setDomNode(node); // trigger re-render on changes
// ...
}, []);
Run Code Online (Sandbox Code Playgroud)
export class FooClass extends React.Component {
state = { ref: null, ... };
onRefChange = node => {
// same as Hooks example, re-render on changes
this.setState({ ref: node });
};
render() {
return <h1 ref={this.onRefChange}>Hey</h1>;
}
}
Run Code Online (Sandbox Code Playgroud)
注意:useRef不通知ref更改。还没有运气与React.createRef()/对象裁判。
这是一个测试用例,它在触发onRefChange回调时删除并重新添加节点:
export function Comp() {
const onRefChange = useCallback(node => {
if (node === null) {
// DOM node referenced by ref has been unmounted
} else {
// DOM node referenced by ref has changed and exists
}
}, []); // adjust deps
return <h1 ref={onRefChange}>Hey</h1>;
}
Run Code Online (Sandbox Code Playgroud)
const [domNode, setDomNode] = useState(null);
const onRefChange = useCallback(node => {
setDomNode(node); // trigger re-render on changes
// ...
}, []);
Run Code Online (Sandbox Code Playgroud)
componentDidUpdate当组件状态或 props 改变时被调用,所以当 a 改变时它不一定会被调用,ref因为它可以根据你认为合适的方式进行改变。
如果您想检查参考是否与之前的渲染相比发生了变化,您可以保留另一个参考来与真实的参考进行检查。
例子
class App extends React.Component {
prevRef = null;
ref = React.createRef();
state = {
isVisible: true
};
componentDidMount() {
this.prevRef = this.ref.current;
setTimeout(() => {
this.setState({ isVisible: false });
}, 1000);
}
componentDidUpdate() {
if (this.prevRef !== this.ref.current) {
console.log("ref changed!");
}
this.prevRef = this.ref.current;
}
render() {
return this.state.isVisible ? <div ref={this.ref}>Foo</div> : null;
}
}
ReactDOM.render(<App />, document.getElementById("root"));Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>Run Code Online (Sandbox Code Playgroud)