React useImperativeHandle, как открыть DOM и внутренние методы? - PullRequest
0 голосов
/ 27 мая 2020

Очень простой вопрос, мне нужно использовать 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 ]

1 голос
/ 27 мая 2020

Обратите внимание, что childRef и inputRef не одно и то же. Однако вы можете выставить 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"/>
1 голос
/ 27 мая 2020

Вы действительно переопределяете исх. Вы хотите использовать вот так:

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 означает ref в FancyInput. ref.current.style (ref ==> childRef.current)

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

   return <FancyInput ref={childRef}/>
}
...