Wie kann ich eine Taste zum Ein- und Ausschalten aller Akkordeons einrichten?
P粉391677921
P粉391677921 2023-08-30 16:57:51
0
2
670
<p>Ich habe eine Komponente, die mithilfe des folgenden Codes ein zusammenklappbares Akkordeon erstellt: </p> <pre class="brush:php;toolbar:false;">import React, {useState} from 'react'; const Collapsible = (props) =>{ const [open, setOpen] = useState(false); const toggle = () => setOpen(!open); } zurückkehren( <div> <button className={props.level} onClick={toggle}>{props.label}</button> {öffnen && ( <div className="toggle"> {props.children} </div> )} </div> ) } Standard exportieren Collapsible;</pre> <p>Ich verwende es an mehreren Stellen in der Hauptanwendung und manchmal auch in anderen Akkordeons. In mehreren Fällen hatte ich tatsächlich keine Ahnung, wie viele Akkordeons es auf der Seite geben würde, da sie dynamisch basierend auf den Daten gerendert wurden. Vor diesem Hintergrund möchte ich in der Hauptanwendung eine Schaltfläche erstellen, die alle Akkordeons ein- und ausschaltet, ohne eine feste Anzahl festlegen zu müssen und ohne alle Akkordeons in der Hauptanwendung (d. h. einige Akkordeons in anderen Komponenten) rendern zu müssen und dann in die Hauptanwendung importiert). </p> <p>Ich habe versucht, Ref-Hooks zu verwenden, um dies zu erreichen: </p> <ol> <li>Referenz in der Schaltfläche der zusammenklappbaren Komponente hinzufügen und von der übergeordneten Komponente über Requisiten darauf zugreifen: </li> </ol> <pre class="brush:php;toolbar:false;"><button className={props.level} onClick={toggle} ref={props.innerRef}>{props.label}</button> ;</pre> <ol start="2"> <li>Fügen Sie den folgenden Verweis in der Hauptanwendung hinzu: </li> </ol> <pre class="brush:php;toolbar:false;">const childRef = useRef(); const openClick = () => childRef.state = true; } const closeClick = () => childRef.state = false; }</pre> <ol start="3"> <li>Verwenden Sie die folgenden Schaltflächen in der Hauptanwendung: </li> </ol> <pre class="brush:php;toolbar:false;"><button onClick = {openClick}> Alle erweitern </button> <button onClick = {closeClick}> Alles einklappen </button></pre> <ol start="4"> <li>Ref beim Rendern zum Akkordeon hinzufügen: </li> </ol> <pre class="brush:php;toolbar:false;"><Collapsible label="" level="content" innerRef={childRef}></pre> <p>Das bringt eigentlich nichts, wahrscheinlich weil die Art und Weise, wie ich in Schritt 2 versucht habe, auf den Status zuzugreifen, falsch war, aber ich dachte, es wäre einen Versuch wert ...</p> <p>Irgendwelche Ideen, ob dies möglich ist? </p>
P粉391677921
P粉391677921

Antworte allen(2)
P粉441076405

您可以使用Redux

  1. 当您渲染手风琴时,给它们一个特定的id并将其保存在存储中。
  2. 创建一个切片openAllAccordions,循环遍历ID,并将属于该ID的手风琴设置为open=true
  3. 创建一个切片closeAllAccordions,循环遍历ID,并将属于该ID的手风琴设置为open=false
P粉809110129

在一个更或多或少任意的组件实例集合中,需要一些协调是很常见的。我成功使用的一种方法是创建一个与关联钩子的Context,组件可以使用该钩子进行注册。该钩子返回共享状态的视图和修改该状态的函数,以满足您的需求。

在这里,您可以创建一个存储每个已注册组件的opener函数并提供openAll/closeAll函数的Context:

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}
    />
  );
};

...还有一个被每个子组件调用的钩子,用于在上下文中注册,并返回熟悉的toggle/open值:

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 };
};

还有一个用于执行批量操作的独立钩子也很方便:

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

  return { openAll, closeAll };
};

Sandbox

请注意,为简单起见,这里只是使用了单独的opener(又名setOpen)函数作为每个已注册组件的唯一标识符。一个灵活的替代方案是使用其他标识符,这样您可以在导航等情况下打开/关闭任意的手风琴。

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage