Reactでページネーションを作成したかったのです。すべてのデータはストアから取得されます。このコードでは、検索エンジンを実装したいと思いました。今回は持っていませんが、それをシミュレートする検索方法を書きました。OK、動作しますが、[こんにちは]をクリックすると、カテゴリ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);
問題はどこにありますか?
あなたは、ReactでStateがどのように機能するかについての一般的な誤解に苦しんでいるようです。this.setState
クラス内またはuseState
フックによって返される「更新関数」を介して状態を更新しても、関連する状態値が「自動的に」変更されることはありません。クラスコンポーネントでは、これはReactの実装がどのように機能するかsetState
(非同期)によるものですが、フックを使用すると、それについて考えるのをやめれば完全に明白になるはずです。setAllItems
は関数allItems
ですが、は配列です-そしてそれらは互いに直接関係することは何もありません。呼び出しsetAllItems
てもallItems
-の値は変更されません。allItems
は単なる変数であり、新しい値を与える唯一の方法は、直接変更または再割り当てすることです。明らかに別の関数を呼び出します。setAllItems
、そうではない引数を使用するとallItems
、おそらくそれを行うことはできません。
代わりに、コンポーネントの再レンダリングをスケジュールします。つまり、コンポーネントを表す関数の後続の呼び出しをスケジュールし、にuseState
対応する呼び出しallItems
が設定した値を返すようにします。しかし、これは必然的にかなり間接的なプロセスです。特に、コンポーネントの次のレンダリングでallItems
必要な値が得られますが、その関数は呼び出されないため(ユーザーがボタンをもう一度クリックするまで)、呼び出しは「正しい」長さで自動的にトリガーされません(フィルタリング後に更新された長さ)。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>
);
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加