Me gustaría tener un enlace personalizado que me proporcione un componente ScrollView y una función para controlar de manera imperativa el desplazamiento de ese componente dado.
Estoy usando una biblioteca llamadareact-native-keyboard-aware-scroll-view , que me permite capturar la referencia del componente a través de un accesorio llamado innerRef . A través de esa referencia tengo acceso a una serie de métodos que puedo usar para manipular el desplazamiento.
La única forma que encontré para que esa "función de control" tuviera acceso a la referencia mientras estaba fuera del alcance del componente ScrollView fue crear esa ref globalmente usando React.createRef como se muestra a continuación:
const ref = createRef(); const ScrollView = ({ children, ...props }) => { return ( <KeyboardAwareScrollView {...props} innerRef={(inner) => { ref.current = inner; //adding ref to scrollview }} > {children} </KeyboardAwareScrollView> ); }; const useScrollTo = () => { const scrollTo = (position) => { if (ref.current && position) { /* controlling scroll using ref */ ref.current.scrollTo({ x: 0, y: position, animate: true }); } }; return { ScrollView, scrollTo }; }; export default useScrollTo; Aunque las declaraciones const en el alcance global crean globales que no son parte del objeto global, me parece antipatrón, por lo que me gustaría saber si hay una forma adecuada de hacerlo sin la necesidad de tener un ref. en el ámbito global como este. ¿Es esto posible?
Aquí hay un ejemplo de este enlace que se usa para ayudar con la validación de formularios en un formulario largo, apuntando al usuario a la entrada que no pudo pasar la validación:
Gracias por el ejemplo de trabajo que proporcionó, así es como manejaría el escenario: https://codesandbox.io/s/frosty-sea-83tvx6?file=/src/ScrollView.js
El gancho personalizado ahora es un gancho real, ya que hace uso de un gancho de reacción:
const useScrollTo = () => { const ref = useRef(); const scrollTo = (position) => { if (ref.current && position) { ref.current.scrollTo({ x: 0, y: position, animate: true }); } }; return { ref, scrollTo, ScrollView }; }; La referencia se crea dentro del enlace, la recupera el Componente de la App y se transmite a su ScrollComponent de desplazamiento:
function App() { const { ref, scrollTo, ScrollView } = useScrollTo(); const [position, setPosition] = useState(0); const [errorPresent, setErrorPresent] = useState(false); const simulateValidation = () => { scrollTo(position); setErrorPresent(true); }; return ( <ScrollView myRef={ref}> ... ... Su componente ScrollView :
const ScrollView = ({ children, myRef, ...props }) => { return ( <KeyboardAwareScrollView {...props} innerRef={(inner) => { myRef.current = inner; }} > {children} </KeyboardAwareScrollView> ); }; No utilicé el envoltorio React.forwardRef por simplicidad, si no le gusta la idea de tener que nombrar sus referencias, puede envolver ScrollView en React.forwardRef() y pasar la referencia con <ScrollView ref={ref}> .
EDITAR: actualicé el ejemplo devolviendo el Componente ScrollView del gancho, aunque personalmente no me gusta esta práctica, entiendo que a algunas personas les gusta usarla para evitar tener que importar módulos repetitivos en sus Componentes.