【问题标题】:How to rerender when refs change如何在 refs 更改时重新渲染
【发布时间】:2020-04-23 07:35:25
【问题描述】:

代码:

import DrawControl from "react-mapbox-gl-draw";

export default function MapboxGLMap() {
    let drawControl = null
    return(
      <DrawControl ref={DrawControl => {drawControl = DrawControl}}/>
    )
}

我想在drawControl 不为空时加载数据。我检查了可能使用回调参考的文档。

那么,如何监听drawControl 的变化并加载数据?

【问题讨论】:

  • ref更新时需要重新渲染,还是用useRef就够了?这样做的方式你不会以任何方式存储参考。您必须使用一些挂钩来存储它、类组件或组件外部的对象(例如商店)。

标签: javascript reactjs ref


【解决方案1】:

虽然组件不会重新渲染,但一旦 current 被填充,useEffect 就会收到 ref。因此,虽然标记的答案也是正确的,但这不是惯用的方法,因为在将 ref 设置为 state 时会导致 1 次不必要的渲染。

export default function MapboxGLMap() {
  const drawControlRef = useRef(null)

  useEffect(() => { 
    // This has a value now.
    console.log(drawControlRef.current)
  }, [])

  return(
    <DrawControl ref={drawControlRef} />
  )
}

如果您希望将 ref 传递给自定义挂钩,请使用 drawControlRef 而不是 drawControlRef.current,然后您也可以在其中的 useEffect 挂钩中访问已填写的 drawControlRef.current

【讨论】:

  • 说callback-ref + useState引起的重新渲染是不必要的,这是不正确的。 需要重新渲染(或直接从传递给ref的回调函数调用操作)以确保我们在引用更新时执行操作,因为组件可能不会在之后再次渲染参考更改。 (在问题的情况下,我们“想在drawControl [is] 不为空时加载数据”)。 (从传递给ref 的回调函数调用动作也可以避免重新渲染,尽管这在性能方面并不是什么大问题。)
【解决方案2】:

您可以使用useEffect 基于useRef 中的更改的回调函数

   function useEffectOnce(cb) {

        const didRun = useRef(false);
        useEffect(() => {
            if(!didRun.current) {
                cb();
                didRun.current = true
            }
        })
    }

【讨论】:

    【解决方案3】:

    useCallback 可以监听 ref 的变化

    export default function MapboxGLMap() {
        const drawControlRef = useCallback(node => {
          if (node !== null) {
            //fetch(...)   load data
          }
        },[]);
    
        return(
          <DrawControl ref={drawControlRef }/>
        )
    }
    

    【讨论】:

    • 非常适合我
    【解决方案4】:

    如果要在 ref 更改后触发重新渲染,则必须使用 useState 而不是 useRef。只有这样才能确保组件会重新渲染。例如:

    function Component() {
      const [ref, setRef] = useState();
    
      return <div ref={newRef => setRef(newRef)} />
    }
    

    useRef 文档中所述:

    请记住,useRef不会在其内容更改时通知您。改变 .current 属性不会导致重新渲染。如果你想在 React 将 ref 附加或分离到 DOM 节点时运行一些代码,你可能需要使用 callback ref 来代替。

    按照here 的建议,存储从 DOM 节点获取的任何值有时可能比存储节点本身更好。

    【讨论】:

    • 感谢您的建议,我尝试了您的代码,但它一直在重复重新渲染。我需要在更新 ref 时重新渲染。我认为回调 ref 可能会帮助我。但我不知道该怎么做
    • 谢谢,我使用回调引用来解决我的问题。
    • @YangYun,你能在代码沙箱中重现重新渲染循环吗?我试过了,但没有发生here
    • 问题是,有时你必须使用参考。
    • 在什么情况下需要使用 ref?可以将元素存储在useState 中,并在每次渲染过程中将其写入ref.current 以获得两者。例如,如果您希望 ref 可以访问而不使其成为挂钩的依赖项,同时在元素更改时强制重新渲染,则很有用。
    猜你喜欢
    • 2020-08-23
    • 1970-01-01
    • 2015-06-04
    • 2013-08-16
    • 2021-01-27
    • 2016-12-30
    • 2021-07-08
    • 2022-07-26
    • 1970-01-01
    相关资源
    最近更新 更多