React useImperativeHandle如何公开DOM和内部方法?

时间:2020-05-27 09:41:07

标签: reactjs react-hooks

一个非常简单的问题,我需要使用useImperativeHandle来向父母公开内部子方法。 但我也想访问ref.current.style,例如,在使用useImperativeHandle时,它是未定义的,任何想法如何通过内部方法传递它?

  useImperativeHandle(ref, () => ({
        someMethod: () => {
            ...
        },
        ...ref
    }));

以上方法可行,但这是正确的方法吗? (同样,我们必须做ref.current.current,这不是很好)

一个简单的例子:

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

function FancyParent() {
   const childRef = useRef()

   useEffect(()=>{
     childRef.current.style.opacity = 0;
     // oups current.style has been ovveriden and is now 
    //undefined
   })

   return <FancyInput ref={childRef}/>
}

2 个答案:

答案 0 :(得分:1)

您实际上是覆盖参考。您想这样使用:

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    opacity: () => {
      inputRef.current.style.opacity = 0
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

function FancyParent() {
   const childRef = useRef()

   useEffect(()=>{
     childRef.current.opacity()
   })

   return <FancyInput ref={childRef}/>
}

如果您想直接在FancyParent中进行交互,则需要使用:

childRef.current.current.style.opacity = 0

在这里,childRef.current在FancyInput中指示refref.current.style(ref ==> childRef.current)

function FancyParent() {
   const childRef = useRef()
   const inputRef = childRef.current
   useEffect(()=>{
     inputRef.current.style.opacity = 0
   })

   return <FancyInput ref={childRef}/>
}

答案 1 :(得分:1)

您必须注意,childRefinputRef是不同的。不过,您可以使用inputRef

childRef中暴露useImperativeHandle

const  {useRef, useEffect, useImperativeHandle, forwardRef} = React;
let FancyInput = forwardRef((props, ref)  => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    inputRef: inputRef.current,
  }));
  return <input ref={inputRef} style={{opacity: 1}}/>;
})

function FancyParent() {
   const childRef = useRef()

   useEffect(()=>{

     childRef.current.inputRef.style.opacity = 0;
   })

   return <FancyInput ref={childRef}/>
}


ReactDOM.render(<FancyParent/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app"/>