Javascript 我们如何知道React ref.当前值何时已更改?

Javascript 我们如何知道React ref.当前值何时已更改?,javascript,reactjs,react-ref,Javascript,Reactjs,React Ref,通常,借助道具,我们可以写作 componentDidUpdate(旧道具){ if(oldProps.foo!==this.props.foo){ console.log('foo prop changed') } } 以检测道具的变化 但是如果我们使用React.createRef(),我们如何检测ref何时更改为新组件或DOM元素?医生们什么都没提 F.e 类Foo扩展了React.Component{ someRef=React.createRef() 组件更新(旧道具){ const

通常,借助道具,我们可以写作

componentDidUpdate(旧道具){
if(oldProps.foo!==this.props.foo){
console.log('foo prop changed')
}
}
以检测道具的变化

但是如果我们使用
React.createRef()
,我们如何检测ref何时更改为新组件或DOM元素?医生们什么都没提

F.e

类Foo扩展了React.Component{
someRef=React.createRef()
组件更新(旧道具){
const refChanged=/*我们在这里放什么*/
如果(参考变更){
console.log('new ref value:',this.someRef.current)
}
}
render(){
// ...
}
}
我们应该自己实现某种旧的价值观吗

F.e

类Foo扩展了React.Component{
someRef=React.createRef()
oldRef={}
componentDidMount(){
this.oldRef.current=this.someRef.current
}
组件更新(旧道具){
const refChanged=this.oldRef.current!==this.someRef.current
如果(参考变更){
console.log('new ref value:',this.someRef.current)
this.oldRef.current=this.someRef.current
}
}
render(){
// ...
}
}

这就是我们应该做的吗?我原以为React会为这项功能添加一些简单的功能。

componentDidUpdate
在组件状态或道具更改时调用,因此当
ref
更改时不一定会调用它,因为它可以根据需要进行变异

如果要检查某个参照是否已从上一次渲染更改,则可以保留另一个参照,并与实际参照进行对比检查

示例

类应用程序扩展了React.Component{
prevRef=null;
ref=React.createRef();
状态={
可见:正确
};
componentDidMount(){
this.prevRef=this.ref.电流;
设置超时(()=>{
this.setState({isVisible:false});
}, 1000);
}
componentDidUpdate(){
if(this.prevRef!==this.ref.current){
log(“ref-changed!”);
}
this.prevRef=this.ref.电流;
}
render(){
返回this.state.isVisible?Foo:null;
}
}
render(,document.getElementById(“根”))

React文档建议使用来检测
ref
值的变化

例如:

export function Foo() {
  const [ref, setRef] = useState(null);

  const onRefChange = useCallback(node => {
    // ref value changed to node
    setRef(node); // e.g. change ref state to trigger re-render
    if (node === null) { 
      // node is null, if DOM node of ref had been unmounted before
    } else {
      // ref value exists
    }
  }, []);

  return <h1 ref={onRefChange}>Hey</h1>;
}

var{useState,useffect,useCallback}=React

因此,在基于类的示例中,我什么时候可以执行该检查?等等,在每次
渲染后不是调用了
componentdiddupdate
?那么,
componentdiddupdate
不是进行检查的地方吗(即使
componentdiddupdate
是由道具或状态更改间接触发的)?@trusktr是的,在道具或状态更改后会间接调用
componentdiddupdate
,但是ref是一个可以被任何东西改变的可变值,React无法知道ref在这个意义上改变了。在类示例中,您将使用
componentDidMount
componentdiddupdate
的组合。我更新了答案。“ref是一个可以被任何东西改变的可变值”,这是真的,但类似地,
this.state
中的任何东西都可以,但是我们显然避免这样做,因为这不是改变状态的方法。同样地,我认为(希望)很明显,我们不应该随意修改道具或裁判。因此,如果我们只允许React modify
ref.current
(仅通过将ref传递到JSX标记中),那么我们必须跟踪旧值的想法似乎是唯一的方法。如果React在这一点上有更多的位置,那就太好了。对于旧的ref(基于函数的ref),只需
setState
在函数中使用新的ref就很容易了,这将触发反应性,而无需手动跟踪旧值。事后看来,这可能更直观(如更明显的如何处理反应性)。(然而,我讨厌函数的每次调用总是以null ref开头,这绝对令人难以置信。他们认为这是为了强制清理,但我认为这比防止糟糕的最终用户代码带来更多的问题)。谢谢。React中的ref功能不理想。例如,在Vue中引用要容易得多。问题是关于React(-:顺便说一句:为了防止回调引用每次都以
null
开头,只需将其定义为类方法(而不是内联箭头函数)或者像上面的测试用例一样,用
useCallback
包装回调。这在底部的一堵文本墙后面会悄悄提到。@Erwol是的,你可以这样做。如果需要重新渲染,当节点更改时,使用
useState
/
setState
。如果节点更改不应触发重新渲染,请使用ref或instance变量(在类的情况下)。如果使用REF,您通常希望编写类似于
this.containerRef.current=currentNode
的内容。
export class FooClass extends React.Component {
  state = { ref: null, ... };

  onRefChange = node => {
    // same as Hooks example
    this.setState({ ref: node });
  };

  render() {
    return <h1 ref={this.onRefChange}>Hey</h1>;
  }
}