【问题标题】:why is useRef not working in this example?为什么 useRef 在此示例中不起作用?
【发布时间】:2020-11-28 05:51:09
【问题描述】:

这是我的反应钩子代码:

function Simple(){
    var [st,set_st]=React.useState(0)
    var el=React.useRef(null)
    if (st<1)
        set_st(st+1)//to force an extra render for a grand total of 2
    console.log('el.current',el.current,'st',st)
    return <div ref={el}>simple</div>
}
ReactDOM.render(<Simple />,document.querySelector('#root') );

我认为它应该渲染两次。第一次 el.current 应该为空,第二次应该指向 div 的 DOM 对象。 运行时,这是输出

el.current null st 0
el.current null st 1

确实,是的,渲染了两次。但是,第二次渲染 el.current 仍然为空。为什么?

解决方案:如下面的 Gireesh Kudipudi 所述。我添加了useEffect

function Simple(){
    var [st,set_st]=React.useState(0)
    var el=React.useRef(null)
    if (st<1)
        set_st(st+1)//to force an extra render for a grand total of 2
    console.log('el.current',el.current,'st',st)
    React.useEffect(_=>console.log('el.current',el.current,'st',st)) //this prints out the el.current correctly
    return <div ref={el}>simple</div>
}
ReactDOM.render(<Simple />,document.querySelector('#root') );

【问题讨论】:

    标签: reactjs react-hooks use-ref


    【解决方案1】:

    这可能是您专注于渲染数量,这不一定是使用钩子时最好的 React 思维方式。心态应该更像我的世界发生了什么变化

    从那时起,尝试添加useEffect 并告诉它您有兴趣查看ref 何时在我的世界中发生变化。试试下面的例子,自己看看行为。

    let renderCounter = 0;
    
    function Simple() {
      const [state, setState] = useState()
      const ref = React.useRef(null)
    
      if (state < 1) {
        /** 
         * We know this alter the state, so a re-render will happen
         */
        setState('foo')
      }
    
      useEffect(() => {
        /**
         * We don't know exactly when is `ref.current` going to
         * point to a DOM element. But we're interested in logging
         * when it happens.
         */
        if (ref.current) {
          console.log(ref.current)
    
          /**
           * Try commenting and uncommenting the next line, and see
           * the amount of renderings
           */
           setState('bar');
        }
    
      }, [ref]);
    
      renderCounter = renderCounter + 1
      console.log(renderCounter);
    
      return <div ref={el}>simple</div>
    }
    

    ref 已经用一个值初始化时,React 将重新渲染,但这并不意味着它会在第二次渲染时发生。

    要回答您的问题,您还没有告诉 react 在ref 更改时该怎么做。

    【讨论】:

    • ref 对象是一个可变对象,它在重新渲染时拥有相同的引用。将其作为依赖项添加到 useEffect 不会重新触发效果。它记录正确值的原因是useEffect 在渲染阶段之后运行
    【解决方案2】:
    class SimpleComponent extends React.Component{
      el = React.createRef(null)
      constructor(props){
        super(props)
        this.state = {
          st:0
        }
      }
      componentDidMount(){
        if(this.state.st<1)
          this.setState(prevState=>{
            return {st:prevState.st+1}
          })
      }
    
      render(){
        console.log('el.current',this.el.current,'st',this.state.st)
        return <div ref={this.el}>simple</div>
      }
    }
    
    ReactDOM.render(<SimpleComponent />,document.querySelector('#root') );
    

    输出是

    el.current null st 0
    el.current <div>​simple​</div>​ st 1
    

    根据Documentation

    ReactDOM.render(element, container[, callback])

    在提供的容器中将 React 元素渲染到 DOM 中并返回组件的引用(或对于无状态组件返回 null)。

    由于您尝试引用功能组件,这可能是原因。由于您的问题,我遇到了有趣的场景。

    如果用作子组件,输出也符合预期

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-17
      • 1970-01-01
      • 2020-08-14
      • 2018-11-14
      • 2014-09-05
      • 2016-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多