【问题标题】:React hooks with Gatsby. onClick changes setState on second Click only与 Gatsby 反应钩子。 onClick 仅在第二次单击时更改 setState
【发布时间】:2019-10-13 20:11:38
【问题描述】:

我正在制作一个个人网站,其中我有一堆风格化的卡片,通过使用 GraphQL 查询创建的数组映射呈现。

那些卡片有一个标签,我的目标是当你点击这个标签时,它会过滤原始数组,只留下包含标签的项目。

去这样的事情


const Tutoriales = ()=> {




    const blog = useStaticQuery(graphql`
    query {
        allMarkdownRemark (
          sort: {fields: frontmatter___date, order: DESC}

         )


        {
            edges {
                node { 
                    frontmatter {
                        title,
                        date,
                        type,
                        abs,
                        tag,
                        featuredImage {
                            relativePath,
                            absolutePath,
                            childImageSharp{
                                fixed(width: 300) {
                                    ...GatsbyImageSharpFixed
                                }
                            }
                        }

                    }
                    html,
                    excerpt,
                    fields {
                        slug
                    }
                }
            }
        }
    }
    `
    );


    let pijon = blog.allMarkdownRemark.edges;
    const [cards, setCards] = useState(pijon);
    const [filter, setFilter] = useState("");

 return (
<div>

{
            cards.map((edge)=> {

 <Card className={classes.card}>
      <CardHeader
                      avatar={
                        <Avatar aria-label="Recipe" className={classes.avatar}>
                          {edge.node.frontmatter.type}
                        </Avatar>
                      }

                      title={<Link className={center.nodecor} to={url}>{edge.node.frontmatter.title}</Link>}
                      subheader={<Link className={center.nodecor} to={url}>{edge.node.frontmatter.date} </Link>}

                    />

 // This is my tag DIV, Im trying to make it work so that when you click
 // on the div, it will use the Filter Hook, to filter the card array


 <div onClick={ () => {
            setFilter(edge.node.frontmatter.tag);


            console.log(filter)
            let filteredCards = cards.filter((card) => {
              return card.node.frontmatter.tag === filter
            }

            )
          setCards(filteredCards);

        }

        }
           className={center.right}>
              {edge.node.frontmatter.tag}  </div>
          </div>


 </Card>

    )
            })
            }

</div>

    )
}

export default Tutoriales



预期的结果是,卡片钩子现在将被过滤,从而使所有不包含所选标签的卡片消失。

但是这样做时,我得到的只是一个空白数组。我知道这与 setState 钩子是异步的有关,并且我一直在阅读有关 UseEffect 的信息,但我似乎无法使其工作。

使用console.log,我意识到,只有第二次点击标签(带有onClick 值)时它才会起作用。

欢迎评论。

【问题讨论】:

    标签: reactjs onclick gatsby setstate


    【解决方案1】:

    你是对的,这是因为 setState 调用是批处理的。因此,如果您调用setFilter 并在同一块中开始使用filter,您实际上是在使用它的前一个值。这就是它第二次起作用的原因。

    setFilter(edge.node.frontmatter.tag);
    console.log(filter);    <- filter has not actually changed yet
    

    最简单的解决方法是删除 const [filter, setFilter] = useState(""); 并直接使用您选择的过滤器:

    <div 
      onClick={() => {
        const filter = edge.node.frontmatter.tag;
        let filteredCards = cards.filter((card) => {
          return card.node.frontmatter.tag === filter
        });
        setCards(filteredCards);
      }}
      className={center.right}
    >
        {edge.node.frontmatter.tag}
    </div>
    

    另一种解决方案是使用 useEffect 挂钩,并在 filter 更改后更新卡片:

    const [cards, setCards] = useState(pijon);
    const [filter, setFilter] = useState("");
    useEffect(() => {
      if (filter) {  // don't do anyhiting when filter is empty on initial render
        const filteredCards = cards.filter((card) => {
          return card.node.frontmatter.tag === filter
        }
        setCards(filteredCards);
      }
    }, [filter, setCards]);
    
    // ...
    
    <div 
      onClick={() => {setFilter(edge.node.frontmatter.tag);}}
      className={center.right}
    >
        {edge.node.frontmatter.tag}
    </div>
    

    【讨论】:

    • 非常感谢。特别是为了给我一个简单的方法(不敢相信这是一个如此简单的修复......)并解释了使用 useEffect 的正确方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 2019-10-12
    • 1970-01-01
    • 2011-01-05
    • 2021-01-14
    相关资源
    最近更新 更多