在 React 组件中切换特定的 div (id)

Toggle specific div (id) within a react component

我有一个使用 post 组件构建的网站,用于在提要中显示文章。在组件内部,我有一个打开模式 onClick 的按钮。我使用 useState 来切换模式,效果非常好。问题是,由于切换是放在组件内部的 modal-div 上。每当我单击其中一个按钮时,每个 post 模式都会打开。我只想打开目标 post 模式(使用 sam post id 作为我单击的按钮)。我不知道该怎么做……在反应中。

    const [toggle, setToggle] = useState (true);
      
    const toggler = () => {
        setToggle(prev => !prev)
    }


...

return (
        <section className="posts">
        {data.allMarkdownRemark.edges.map((edge) => {
            return (
                <div className="post">
                    <div className="postDescrip">
                        <h2 className="postTitle">{edge.node.frontmatter.title}</h2>
                        <h2 className="name">{edge.node.frontmatter.name}</h2>

                        <button className="readMoreBtn" onClick={toggler}>{toggle ? <h2 className="readMore">Read more</h2> : <h2 className="readMore">Read less</h2>} 
                        </button>
                    </div>
                
                    <Img className="postImg" fluid={edge.node.frontmatter.featuredImage.childImageSharp.fluid} /> 

                    <div className={toggle ? 'hide' : 'postCopy'} >
                        <Close close={toggler} />
                        <h3>{edge.node.frontmatter.details}</h3>
                        <div className="copy" dangerouslySetInnerHTML= {{__html: edge.node.html}}></div>
                        <h4>Read the full article in Issue One</h4>
                    </div>
                </div>
            )}
        )}
        </section>
    )
}
export default Posts;

在尝试使用对象而不是布尔值的建议解决方案之后。我现在收到此错误消息 [错误信息][1]为以下代码:

    const [toggles, setToggles] = useState ({});
    
    let id;
    const createToggler = (id) = () => {
        setToggles(prev => { [id] : !prev[id] }) 
        // setToggle(prev => { ...prev, [id]: !prev[id] }) // or support multi modal at same time. but I think you don't want it.
    }
    
    const data = useStaticQuery(graphql`
        query {
            allMarkdownRemark (
                sort: { order: DESC, fields: [frontmatter___date] }
                ){
                edges {
                    node {
                        frontmatter {
                            id
                            title
                            name
                            details
                            featuredImage {
                                childImageSharp {
                                    fluid(maxWidth: 800) {
                                        ...GatsbyImageSharpFluid
                                    }
                                }
                            }
                        }
                        html
                        fields {
                            slug
                        }
                    }
                }
            }
        }
    `)

    
    
    return (
        <section className="posts">
        {data.allMarkdownRemark.edges.map((edge) => {
            const id = edge.node.frontmatter.id;
            const toggle = toggles[id];
            const toggler = createToggler(id);
            return (
                <div className="post" id={edge.node.frontmatter.id}>
                    <div className="postDescrip">
                        <h2 className="postTitle">{edge.node.frontmatter.title}</h2>
                        <h2 className="name">{edge.node.frontmatter.name}</h2>

                        <button className="readMoreBtn" onClick={toggler}>{toggle ? <h2 className="readMore">Read more</h2> : <h2 className="readMore">Read less</h2>} 
                        </button>
                    </div>
                
                    <Img className="postImg" fluid={edge.node.frontmatter.featuredImage.childImageSharp.fluid} /> 

                    <div className={toggle ? 'hide' : 'postCopy'} id={edge.node.frontmatter.id}>
                        <Close close={toggler} />
                        <h3>{edge.node.frontmatter.details}</h3>
                        <div className="copy" dangerouslySetInnerHTML= {{__html: edge.node.html}}></div>
                        <h4>Read the full article in Issue One</h4>
                    </div>
                </div>
            )}
        )}
        </section>
    )
}
export default Posts;
            


  [1]: https://i.stack.imgur.com/VhIYF.png

像这样。 使用对象而不是单个布尔值。

    const [toggles, setToggles] = useState ({});
      
    const createToggler = (id) = () => {
        setToggle(prev => { [id]: !prev[id] }) // atmost one id is true. others is undefine or false.
        // setToggle(prev => { ...prev, [id]: !prev[id] }) // or support multi modal at same time. but I think you don't want it.
    }


...

return (
        <section className="posts">
        {data.allMarkdownRemark.edges.map((edge) => {
            const id = ... // get your id form edge.
            const toggle = toggles[id];
            const toggler = createToggler(id);
            return (
                <div className="post">
                    <div className="postDescrip">
                        <h2 className="postTitle">{edge.node.frontmatter.title}</h2>
                        <h2 className="name">{edge.node.frontmatter.name}</h2>

                        <button className="readMoreBtn" onClick={toggler}>{toggle ? <h2 className="readMore">Read more</h2> : <h2 className="readMore">Read less</h2>} 
                        </button>
                    </div>
                
                    <Img className="postImg" fluid={edge.node.frontmatter.featuredImage.childImageSharp.fluid} /> 

                    <div className={toggle ? 'hide' : 'postCopy'} >
                        <Close close={toggler} />
                        <h3>{edge.node.frontmatter.details}</h3>
                        <div className="copy" dangerouslySetInnerHTML= {{__html: edge.node.html}}></div>
                        <h4>Read the full article in Issue One</h4>
                    </div>
                </div>
            )}
        )}
        </section>
    )
}
export default Posts;

我这样解决了我的问题

import React, {useState} from "react"
import Img from "gatsby-image"
import './posts.css';
import cancel from '../images/cancel.png'

const Post = ({title, name, id, image, details, html}) => {   
    const [toggle, setToggle] = useState (true);

    const toggler = () => {
        setToggle(prev => !prev)
    }

    const selectPost= (event) =>{
        let id = event.target.id,
            postCopy = document.getElementById('hide' + id);
            toggler.call(postCopy);
    } 

        
    return (
        <div className="post">
            <div className="postDescrip">
                <h2 className="postTitle">{title}</h2>
                <h2 className="name">{name}</h2>
                <button className="readMoreBtn" onClick={selectPost}>{toggle ? <h2 id={id} className="readMore">Read more</h2> : <h2 id={id} className="readMore">Read less</h2>} 
                </button>
            </div>
        
            <Img className="postImg" fluid={image} />
            <div id={'hide' + id} className={toggle ? 'hide' : 'postCopy'} >
                <button aria-label="Close" onClick={selectPost} className="closeBtn">
                    <img alt="close-button" src={cancel}/>
                </button>
                <h3>{details}</h3>
                <div className="copy" dangerouslySetInnerHTML= {html}></div>
                <a href="/#footer"><h4>Read the full article in Issue One</h4></a>
            </div>
        </div>
    )
}
export default Post;