简体   繁体   English

反应按钮不重新渲染组件

[英]React button not rerendering the component

I am making a blog with React and Sanity, and am trying to use buttons to allow the user to sort blog posts by tag (category).我正在使用 React 和 Sanity 制作博客,并尝试使用按钮允许用户按标签(类别)对博客文章进行排序。 Currently, the sorting works fine if I hard code the tag I want to sort the posts by, but I want to be able to use buttons to change the sort tag.目前,如果我对要对帖子进行排序的标签进行硬编码,排序工作正常,但我希望能够使用按钮来更改排序标签。 Right now the button is able to change text on the screen to the correct category, but It does not update the visible posts (does not actually sort them).现在该按钮能够将屏幕上的文本更改为正确的类别,但它不会更新可见的帖子(实际上不会对它们进行排序)。

Here is my code for the blog page:这是我的博客页面代码:

import React from "react";
import { useState, useEffect } from "react"

import Footer from "../Footer";
import Header from "./Header";

import client from "../../client"
import BlockContent from "@sanity/block-content-to-react";

import { Link } from "react-router-dom";

const Blog = () =>
{
    const [posts, setPosts] = useState([])
    const [sort, setSort] = useState("all")
    
    useEffect(() => {
        client.fetch(
            //This line sorts posts by the value of 'keyword' 
            `*[_type == "post" && $keyword in tags] { 
                title,
                slug,
                body,
                mainImage {
                    asset -> {
                        _id,
                        url
                    },
                    alt
                },
                tags,
                publishedAt
            }`,{"keyword":sort} //This line sets the value of 'keyword' to the value of 'sort'
        )
        .then((data) => setPosts(data))
        .catch(console.error)
    }, [])

    //This function prints the tag that was clicked to the console and updates the 
    //value of 'sort'. It is supposed to rerender the component to display only the
    //posts associated with the tag clicked, but it does not.
    function sortPosts(e) {
        console.log(e)
        setSort(e)
    }

    return (
        <div className = "bg-gray-100 dark:bg-zinc-900">
            <Header />
            <div className = "" >
                <p className = "title pt-32">Welcome to My Blog!</p>

                //This line correctly displays the tag that is supposed to determine which posts to display
                <p className = "text-center font-semibold">Currently showing: {sort} posts</p>

                <div className = "flex items-center justify-center mt-16">
                    <div className = "grid grid-cols-1 xl:grid-cols-3 lg:grid-cols-2 md:grid-cols-1 gap-10 mx-16">
                    {posts.map((post) => (
                        <article key={post.slug.current} className = "rounded-xl max-w-sm bg-white dark:bg-zinc-950 shadow-xl dark:shadow-gray-100/10">
                            <img src={post.mainImage.asset.url} alt={post.title} className = "object-fill object-center rounded-t-xl" />
                            <div className = "p-6">
                                <p className = "text-2xl font-semibold mb-3 dark:text-gray-100">{post.title}</p>
                                {post.tags.map((tags, key) => (
                                    <div className = "inline-block">

                                        //This line displays a button for each tag associated with the current post and calls the sortPosts function
                                        <button key = {key} onClick={() => sortPosts(tags)} className = "px-2 inline-flex mb-2 mr-2 rounded-2xl hover:bg-white bg-gray-100 dark:hover:bg-zinc-950 dark:bg-zinc-800 dark:text-white duration-300 transition-colors cursor-pointer">{tags}</button>

                                    </div>
                                ))}
                                <div class = "preview">
                                    <BlockContent blocks={post.body} projectId="2hp9gld0" dataset="production" />
                                </div>
                                <button className="button-main items-center mt-2 dark:text-gray-100 block">
                                    <Link to = {`/blog/${post.slug.current}`} className = "">Read Full Article</Link>
                                </button>
                            </div>
                        </article>
                    ))}
                    </div>
                </div>
            </div>
            <div className = "pb-10 bg-gray-100 dark:bg-zinc-900">
                <Footer />
            </div>
        </div>
    )
}

export default Blog;

As I said, this code works perfectly fine other than actually rerendering the correct posts when a button is clicked to sort by a specific tag.正如我所说,除了在单击按钮以按特定标签排序时实际重新呈现正确的帖子之外,此代码工作得非常好。 Any help is appreciated!任何帮助表示赞赏!

If you fetch data and setPosts in useEffect , You should add sort state to useEffect dependency, to update the posts when you change the sort state value by setSort .如果您在useEffect中获取数据和setPosts ,则应将sort state 添加到useEffect依赖项,以便在您通过setSort更改sort state 值时更新帖子。 like below:如下所示:

    const [posts, setPosts] = useState([])
    const [sort, setSort] = useState("all")
    
    useEffect(() => {
        client.fetch(
            //This line sorts posts by the value of 'keyword' 
            ...
        .then((data) => setPosts(data))
        .catch(console.error)
    }, [sort])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM