首页 > 解决方案 > 在反应组件中切换特定的 div (id)

问题描述

我有一个使用后期组件构建的网站,用于在提要中显示文章。在组件内部,我有一个打开模态 onClick 的按钮。我使用 useState 来切换模式,它工作得很好。问题是,由于切换是放在组件内的 modal-div 上。当我单击其中一个按钮时,每个帖子模式都会打开。我只想打开目标帖子模式(使用 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

标签: reactjsreact-component

解决方案


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

    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;

推荐阅读