Maison  >  Questions et réponses  >  le corps du texte

Comment puis-je configurer un bouton pour allumer et éteindre tous les accordéons ?

<p>J'ai un composant qui crée un accordéon pliable en utilisant le code suivant : </p> <pre class="brush:php;toolbar:false;">importer React, {useState} depuis 'react'; const Collapsible = (accessoires) =>{ const [open, setOpen] = useState(false); const bascule = () => setOpen(!ouvert); } retour( <div> <button className={props.level} onClick={toggle}>{props.label}</button> {ouvrir && <div className="toggle"> {accessoires.enfants} </div> )} </div> ) } exporter par défaut Pliable ;</pre> <p>Je l'utilise à plusieurs endroits dans l'application principale et parfois dans d'autres accordéons. Dans plusieurs cas, je n'avais en fait aucune idée du nombre d'accordéons qu'il y aurait sur la page, car ils étaient rendus dynamiquement en fonction des données. Dans cet esprit, je souhaite créer un bouton dans l'application principale qui active (et désactive) tous les accordéons sans avoir à définir un nombre fixe et sans avoir à restituer tous les accordéons dans l'application principale (c'est-à-dire certains accordéons dans d'autres composants). puis importé dans l'application principale). </p> <p>J'ai essayé d'utiliser des crochets de référence pour y parvenir : </p> <ol> <li>Ajoutez une référence dans le bouton du composant pliable et accédez-y depuis le composant parent via les accessoires : </li> </ol> <pre class="brush:php;toolbar:false;"><button className={props.level} onClick={toggle} ref={props.innerRef}>{props.label}</button> ;</pré> <ol start="2"> <li>Ajoutez la référence suivante dans l'application principale : </li> </ol> <pre class="brush:php;toolbar:false;">const childRef = useRef(); const openClick = () => childRef.state = vrai ; } const closeClick = () => childRef.state = faux ; }</pré> <ol start="3"> <li>Utilisez les boutons suivants dans l'application principale : </li> </ol> <pre class="brush:php;toolbar:false;"><bouton onClick = {openClick}> Développer tout </bouton> <bouton onClick = {closeClick}> Tout réduire </bouton></pre> <ol start="4"> <li>Ajouter une référence à l'accordéon lors du rendu : </li> </ol> <pre class="brush:php;toolbar:false;"><Collapsible label="" level="content" innerRef={childRef}></pre> <p>En réalité, cela ne fait rien, probablement parce que la façon dont j'essayais d'accéder à l'état à l'étape 2 était erronée, mais j'ai pensé que cela valait la peine d'essayer...</p> <p>Des idées pour savoir si cela est possible ? </p>
P粉391677921P粉391677921386 Il y a quelques jours566

répondre à tous(2)je répondrai

  • P粉441076405

    P粉4410764052023-08-31 15:23:23

    Vous pouvez utiliser Redux.

    1. Lorsque vous effectuez le rendu des accordéons, attribuez-leur un identifiant spécifique et enregistrez-le dans le stockage.
    2. Créez une trancheopenAllAccordions, parcourez les identifiants et définissez l'accordéon appartenant à cet identifiant sur open=true
    3. Créez une tranchecloseAllAccordions, parcourez les identifiants et définissez l'accordéon appartenant à cet identifiant sur open=false

    répondre
    0
  • P粉809110129

    P粉8091101292023-08-31 12:37:09

    Dans une collection plus ou moins arbitraire d'instances de composants, il est courant d'avoir besoin d'une certaine coordination. Une approche que j'ai utilisée avec succès consiste à créer un Context avec un hook associé avec lequel les composants peuvent être enregistrés. Ce hook renvoie une vue de l'état partagé et une fonction qui modifie cet état en fonction de vos besoins.

    Ici, vous pouvez créer un contexte qui stocke les opener函数并提供openAll/closeAllfonctions pour chaque composant enregistré :

    const AccordionProvider = ({ children }) => {
      const [openers] = useState(new Set());
    
      // 当创建时,是否应该展开新的可折叠项?
      //(支持递归展开是必要的)
      const [defaultOpen, setDefaultOpen] = useState(false);
    
      const register = useCallback(
        (opener) => {
          openers.add(opener);
          return () => openers.delete(opener); // 返回一个用于`useEffect`的取消注册函数
        },
        [openers]
      );
    
      const openAll  = useCallback(() => {
        setDefaultOpen(true);
        openers.forEach(opener => opener(true)),
      }, [setDefaultOpen, openers]);
    
      const closeAll = useCallback(() => {
        setDefaultOpen(false);
        openers.forEach(opener => opener(false)),
      }, [setDefaultOpen, openers]);
    
      return (
        <AccordionContext.Provider
          value={{ register, openAll, closeAll, defaultOpen }}
          children={children}
        />
      );
    };
    

    ...Il existe également un hook appelé par chaque composant enfant pour s'enregistrer dans le contexte et renvoyer la valeur toggle/open familière :

    const useAccordionAsClient = () => {
      const { register, defaultOpen } = useContext(AccordionContext);
    
      const [open, opener] = useState(defaultOpen);
      const toggle = useCallback(() => opener((open) => !open), [opener]);
    
      useEffect(() => register(opener), [register, opener]);
    
      return { toggle, open };
    };
    

    Il existe également un hook séparé pour effectuer des opérations par lots, ce qui est également pratique :

    const useAccordionAsManager = () => {
      const { openAll, closeAll } = useContext(AccordionContext);
    
      return { openAll, closeAll };
    };
    

    Bac à sable

    Veuillez noter que par souci de simplicité, une fonction opener(又名setOpen) distincte est utilisée ici comme identifiant unique pour chaque composant enregistré. Une alternative flexible consiste à utiliser d'autres identifiants afin de pouvoir ouvrir/fermer des accordéons arbitraires dans la navigation, etc.

    répondre
    0
  • Annulerrépondre