【问题标题】:hook state doesn't update automaticlly钩子状态不会自动更新
【发布时间】:2021-01-06 06:47:47
【问题描述】:

我想在 React 中创建分页。所有数据均来自商店。在这段代码中,我想实现搜索引擎。这次我没有这个,但我写了模拟那个的搜索方法。好的,它可以工作,但是 - 在我点击你好之后,它只显示类别 2 中的项目,但它一直显示相同的页面(在我的情况下为 3)。如果我再点击 2 次,它只显示 1 页。我在搜索中添加了 setCountItems 和 setPages,因为这个钩子不会自动更新。

import React, { useEffect, useState, useRef } from 'react'
import { connect} from 'react-redux'
import Article from './article'

const ArticlesContainer = ({ articles }) => {
    const [allItems, setAllItems] = useState(articles.list);
    const [pageNumber, setPageNumber] = useState(1);
    const [perSite, setPerSite] = useState(10);
    const [totalItems, setCountItems] = useState(allItems.length);
    const from = (pageNumber - 1) * perSite;
    const to = ((pageNumber - 1) * perSite) + perSite;
    const [pages, setPages] = useState(Math.ceil(totalItems / perSite));

    const handlePageClick = (i) => {
        setPageNumber(i);
    }
    const search = () => {
        setAllItems(allItems.filter(x => x.category=== 2 ));
        setCountItems(allItems.length);
        setPages(Math.ceil(totalItems / perSite));

    }



    const Pagination = ({pages}) => {
        let list = []
        for(let i = 1; i<=pages; i++){
            list.push(<li key={i} onClick={() => handlePageClick(i)}>{i}</li>)
        }
        return list;
    }

    return (
        <React.Fragment>
            <a onClick={search}>Hello</a>
            {allItems.slice(from, to).map(article =>
                <Article key={article.id} article={article} />
            )}
            <div className="row">
                <ul>
                    <Pagination pages={pages} />
                </ul>
            </div>
        </React.Fragment>
    );
}
const mapStateToProps = state => ({
    articles: state.articles
})

export default connect(mapStateToProps, null)(ArticlesContainer);

问题出在哪里?

【问题讨论】:

    标签: javascript reactjs pagination frontend


    【解决方案1】:

    您似乎对 React 中 State 的工作方式存在普遍误解。更新状态,无论是通过类中的this.setState 还是通过useState 钩子返回的“更新函数”,都不会“自动”改变相关的状态值。在类组件中,这是因为 React 对 setState 的实现是如何工作的(它是异步的),但是对于 Hooks,如果你停下来想一想,它应该是非常明显的。 setAllItems 是一个函数,而 allItems 是一个数组——它们之间没有任何直接的关系。调用setAllItems 不会改变allItems 的值——因为它怎么可能呢? allItems 只是一个变量,给它一个新值的唯一方法是直接改变或重新分配它 - 显然调用一个单独的函数 setAllItems,其参数不是 allItems,不可能这样做。

    它所做的是安排组件的重新渲染 - 即安排代表组件的函数的后续调用 - 并确保与 allItems 对应的 useState 调用随后将返回您设置的值。但这必然是一个相当间接的过程。特别是,allItems 将在组件的 next 渲染中具有您想要的值,但不会调用 search 函数(直到用户再次单击该按钮),所以setCountItems(allItems.length); 调用不会以“正确”长度(过滤后更新的长度)自动触发。

    在您的情况下,问题的解决方案非常简单。您通过引入太多状态变量使您的组件过于复杂,其中大多数状态变量相互依赖。而不是const [totalItems, setCountItems] = useState(allItems.length);,只需输入const totalItems = allItems.length; - 然后这将在每次渲染时自动重新计算为正确的值。你不需要 setCountItems 函数,因为你知道它总是等于 allItems.length - 它不会独立变化。

    同样,您可以在此组件中大大简化许多其他内容,因为唯一可以独立变化并因此需要成为状态一部分的内容是文章列表和页码。这就是我重写你的组件的方式:

    const perSite = 10;
    
    const ArticlesContainer = ({ articles }) => {
        const [allItems, setAllItems] = useState(articles.list);
        const [pageNumber, setPageNumber] = useState(1);
    
        const totalItems = allItems.length;
        const from = (pageNumber - 1) * perSite;
        const to = ((pageNumber - 1) * perSite) + perSite;
        const pages = Math.ceil(totalItems / perSite);
    
        const handlePageClick = (i) => {
            setPageNumber(i);
        }
        const search = () => {
            setAllItems(allItems.filter(x => x.category=== 2 ));
        }
    
        const Pagination = ({pages}) => {
            let list = []
            for(let i = 1; i<=pages; i++){
                list.push(<li key={i} onClick={() => handlePageClick(i)}>{i}</li>)
            }
            return list;
        }
    
        return (
            <React.Fragment>
                <a onClick={search}>Hello</a>
                {allItems.slice(from, to).map(article =>
                    <Article key={article.id} article={article} />
                )}
                <div className="row">
                    <ul>
                        <Pagination pages={pages} />
                    </ul>
                </div>
            </React.Fragment>
        );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-29
      • 1970-01-01
      • 2021-08-08
      • 1970-01-01
      • 2020-04-19
      • 2021-08-17
      • 2021-05-19
      • 1970-01-01
      相关资源
      最近更新 更多