Search code examples
javascripthtmlreactjsdocusaurus

How to add or remove the "open" attribute from all details tags in a react component?


I have a page with a React component that uses multiple detail/summary tags:

const React = require("react");

class samplePage extends React.Component {
  render() {
    const siteConfig = this.props.config;
    return (

        <div>
            <details>
                <summary>
                    First text detail.
                </summary>
            </details>
            <details>
                <summary>
                    Second text detail.
                </summary>
            </details>
            <details>
                <summary>
                    Third text detail.
                </summary>
            </details>

            <button onClick="OpenAll()">Open All Details.</button>
            <button onClick="CloseAll()">Close All Details.</button>
        </div>
    );
  }
}

module.exports = samplePage;

I have a global siteConfig.js to configure my scripts:

scripts: [
    "js/script1.js",
    "js/script2.js",
    "js/script3.js"
],

With 2 functions to add or remove the "open" attribute from the above detail tags:

function CloseAll() {
  $("details").removeAttr("open");
}

function OpenAll() {
    $("details").attr("open", "open");
}

I know the 2 functions in my main script file are imported through siteConfig.js, as my other functions are working without issue. As can be seen from the sample page, the button tags that initiate the OpenAll / CloseAll functions are located within a div with the other detail tags.

I thought my method was good, but neither button produces the intended effect. I suspect this has something to do with the function scope or something about my current set-up (I'm using Docusaurus, which is kinda similar to "Create React App"). I don't think I've done anything out of the ordinary for a project like this. Appreciate any feedback.


Solution

  • Use state to set the attribute to true or false, like that. (Note that you can use hooks like here but also good old state and setState. Also you don't need siteConfig or the two functions defined there.

    const React = require("react");
    
    const samplePage = () => {
        const [isOpen, setIsOpen] = React.useState(false); 
    
        return (
            <div>
                <details open={isOpen}>
                    <summary>
                        First text detail.
                    </summary>
                </details>
                <details open={isOpen}>
                    <summary>
                        Second text detail.
                    </summary>
                </details>
                <details open={isOpen}>
                    <summary>
                        Third text detail.
                    </summary>
                </details>
    
                <button onClick={() => setIsOpen(false)}>Open All Details.</button>
                <button onClick={() => setIsOpen(true)}>Close All Details.</button>
            </div>
        );
      }
    }
    
    module.exports = samplePage;