如何在 refs 更改时重新渲染

IT技术 javascript reactjs ref
2021-04-19 22:01:55

代码:

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

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

我想在drawControl非空时加载数据我检查了可能使用回调引用的文档。

那么,我如何监听drawControl更改并加载数据?

4个回答

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

function Component() {
  const [ref, setRef] = useState();

  return <div ref={newRef => setRef(newRef)} />
}

useRef文档中所述:

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

有时可能更好地存储任何值,你从DOM节点获得,如建议在这里,而不是存储节点本身。

@YangYun,你能在代码沙盒中重现重新渲染循环吗?我试过了,但这里不会发生
2021-05-25 22:01:55
在什么情况下需要使用 ref?可以将元素存储在 a 中useState,并ref.current在每次渲染过程中将其写入 a以获取两者。例如,如果您希望 ref 可访问而不使其依赖于钩子,同时在元素更改时强制重新渲染,则很有用。
2021-05-25 22:01:55
问题是,有时您必须使用引用。
2021-06-04 22:01:55
谢谢,我使用回调引用来解决我的问题。
2021-06-05 22:01:55
感谢您的建议,我尝试了您的代码,但它一直重复重新渲染。我需要在 ref 更新时重新渲染。我认为回调参考可能会帮助我。但我不知道该怎么做
2021-06-08 22:01:55

useCallback 可以监听 ref 更改

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

    return(
      <DrawControl ref={drawControlRef }/>
    )
}
非常适合我
2021-05-30 22:01:55

虽然组件不会重新渲染,useEffect但会在current填充后接收 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,然后您也可以访问其中drawControlRef.currentuseEffect钩子中的填充

说 callback-ref + useState 引起的重新渲染是不必要的,这是错误的。必要的重新渲染(或从调用回调函数,直接作用传递到ref),以确保我们执行一个动作时,裁判的更新,因为组件可能不裁判更改后再次渲染。(在问题的情况下,我们“想要在drawControl[is] 不为空时加载数据”)。(从传递给的回调函数中调用动作ref也避免了重新渲染,尽管在性能方面这不是什么大问题。)
2021-06-11 22:01:55

您可以使用useEffect基于变化的回调函数useRef

   function useEffectOnce(cb) {

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