web-dev-qa-db-fra.com

React Hooks - Passer ref à l'enfant pour utiliser ScrollIntoView

J'ai deux composants. Un parent et un enfant.

À l'intérieur du composant parent, j'ai un bouton. Si l'utilisateur clique sur ce bouton, je veux faire un ScrollIntoView vers un autre bouton à l'intérieur du composant enfant.

Je suppose que je veux définir une référence au bouton childs a afin que je puisse faire un dans le bouton parent onClick:

ref.scrollIntoView({block: 'end', behavior: 'smooth'});

qui fera défiler jusqu'au bouton dans le composant enfant.

Voici un exemple minifié:

ParentComponent.jsx

import React, {useRef} from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = props => {
  const childReference = useRef(null);

  const onClick = () => {
    childReference.scrollIntoView({block: 'end', behavior: 'smooth'});
  }

  return (
    <>
      <...some other components>
      <Button onClick={onClick}>Click me to be forwarded</Button>
      <ChildComponent ref={childReference}/>
    </>
  );
};

ChildComponent.jsx

import React from 'react';

const ChildComponent = (props, ref) => {

  const { name, value, description } = props;

  return (
    <...some other components>
    <Button ref={ref}>You should be forwarded to me</Button>
  );
};

ChildComponent.propTypes = {
  name: PropTypes.string.isRequired,
  value: PropTypes.number,
  description: PropTypes.string,
};

ChildComponent.defaultProps = {
  value: 0,
  description: '',
};

export default React.forwardRef(ChildComponent);

Je connais le code ci-dessus ne fonctionne pas, c'était juste pour illustrer ce que j'essaye d'accomplir.

J'ai vraiment essayé toutes les autres solutions que j'ai pu trouver sur Google et elles semblent toutes si faciles, mais aucune d'entre elles ne semble fonctionner pour mon cas d'utilisation. J'ai également essayé d'utiliser forwardRef, mais cela ne résout pas le problème pour moi.

METTRE À JOUR

Je suppose que j'étais un peu vague sur ce qui ne fonctionnait pas. J'ai reçu beaucoup de messages d'erreur différents avec l'implémentation.

Voici l'un d'entre eux:

Les composants fonctionnels ne peuvent pas recevoir de réf. Les tentatives d'accès à cette référence échoueront. Vouliez-vous utiliser React.forwardRef ()?

Solution

D'accord. J'ai pensé assembler les pièces ici avec la solution fournie par @Vencovsky.

Voici l'implémentation complète avec les deux exemples de composants vus dans la question:

ParentComponent.jsx

import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = props => {
  const childReference = useRef(null);

  const scrollIntoView = () => {
    childReference.current.scrollIntoView({block: 'center', inline: 'center', behavior: 'smooth'});
  }

  return (
    <>
    <...some other component>
    <Button onClick={scrollIntoView}>Click me to be forwarded</Button>
    <ChildComponent ref={childReference}
    </>
  );
};

export default ParentComponent;

ChildComponent.jsx

import React, {forwardRef} from 'react';
import PropTypes from 'prop-types';

const ChildComponent = forwardRef((props, ref) => {
  const { name, value, description } = props;

  return(
    <>
      <...some other components>
      <Button ref={ref}>You should be forwarded to me</Button>
    </>
  );
});

ChildComponent.propTypes = {
  name: PropTypes.string.isRequired,
  value: PropTypes.number,
  description: PropTypes.string,
};

ChildComponent.defaultProps = {
  value: 0,
  description: '',
};

export default ChildComponent;
3
Zeliax

Modifier 2:

Je suppose que tu fais quelque chose comme

const ChildComponent = (props, ref) => { ... }

ChildComponent.propTypes = { ... }

export default React.forwardRef(ChildComponent)

Mais ce que vous devez faire est de passer propTypes après React.forwardRef, Comme ceci:

const ChildComponent = (props, ref) => { ... }          

const ForwardComponent = React.forwardRef(ChildComponent)

ForwardComponent.propTypes = { ... }

export default ForwardComponent

Une meilleure façon de le faire serait comme

//                     using forwarRef
const ChildComponent = React.forwarRef((props, ref) => {

  const { name, value, description } = props;

  return (
    <...some other components>
    <Button ref={ref}>You should be forwarded to me</Button>
  );
});

Vous n'aurez alors pas besoin de changer propTypes et de créer un autre composant.

Éditer:

Lors de votre modification, je peux voir que vous avez oublié d'utiliser React.forwardRef.

Tu devrais ajouter

export default React.forwardRef(ChildComponent)

Dans votre fichier ChildComponent (exportez-le avec forwardRef).


Qu'est-ce qui ne fonctionne pas? Obtenez-vous une erreur? Vous devriez mieux expliquer ce qui se passe, mais je vais essayer de deviner.

Il y a quelque chose qui peut empêcher cela de fonctionner.

  1. Vous devez utiliser ref.current.foo au lieu de ref.foo
  2. Comme l'a dit @JeroenWienk:

    Il semble que votre bouton soit également un composant personnalisé. Êtes-vous sûr que la référence est passée à l'élément de bouton html à l'intérieur?

  3. Pour utiliser le deuxième paramètre d'un composant fonctionnel, vous devez utiliser React.forwardRef . par exemple. export default React.forwardRef(ChildComponent)
1
Vencovsky