【问题标题】:Toggle specific div (id) within a react component在反应组件中切换特定的 div (id)
【发布时间】:2021-05-10 12:04:24
【问题描述】:

我有一个使用后期组件构建的网站,用于在提要中显示文章。在组件内部,我有一个打开模态 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

【问题讨论】:

  • map 中的所有内容移动到具有自己独立状态的单独组件中,这比跟踪父级中每个元素的切换状态要好

标签: reactjs react-component


【解决方案1】:

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

    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;

【讨论】:

    【解决方案2】:

    我这样解决了我的问题

    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;
                
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-18
      • 2020-11-20
      • 1970-01-01
      • 2022-08-21
      • 1970-01-01
      • 2021-01-09
      • 2019-12-08
      • 1970-01-01
      相关资源
      最近更新 更多