[英]Looping through post categories via WordPress REST API - React
我正在嘗試找出使用 WordPress REST API 進行循環的問題。
我擁有的:
我正在使用其余 api 類別端點“/wp/v2/categories”。 我正在遍歷返回的每個類別(總共 7 個類別)並為每個類別創建一個按鈕。 到目前為止,我有那個工作。 代碼如下所示:
const Posts = ({ state }) => {
const [categories, setCategories] = useState([]);
useEffect(() => {
fetch(state.source.api + "/wp/v2/categories")
.then(response => response.json())
.then(data => {
setCategories(data);
})
}, []);
console.log(categories);
return (
<>
{categories.length > 0 ? (
categories.map((category, i) => {
return (
<button key={i}>{category.name}</button>
)
})
) : (
<p>Loading...</p>
)
}
</>
)
}
我想要做什么:我試圖在按鈕下方有一個部分,當點擊按鈕時,它將列出每個類別的博客文章。 因此,當頁面最初加載時,所有博客文章都會加載,但是當您單擊“書籍”類別時,例如,只會顯示“書籍”類別中的文章。 我知道我必須為按鈕創建一個事件處理程序,所以我將按鈕更新為<button key={i} onClick={handleShowPosts}>{category.name}</button>
,並開始創建:
const handleShowPosts = () => {
};
但我對如何做到這一點有點困惑。 我是否需要將{category.name}
傳遞給const handleShowPosts = ({category.name}) => {
,我將如何在循環遍歷每個類別以獲取帖子時執行此操作?
編輯:
我應該澄清一下,查看所有帖子的端點是/wp/v2/categories
,但查看特定類別帖子的端點是"/wp/v2/posts?categories=" + category.id
。
好吧,如果我沒有誤解你的目標和數據結構,這里有一個例子展示你如何做到這一點。 正如我在評論中試圖解釋的那樣,您可以設置類別名稱狀態並有條件地呈現帖子。
const categoriesData = [ { name: "books", posts: [ { id: 1, name: "foo" }, { id: 2, name: "bar" } ] }, { name: "movies", posts: [ { id: 1, name: "fizz" }, { id: 2, name: "buzz" } ] } ]; function Main() { const [categories, setCategories] = React.useState(categoriesData); const [catName, setCatName] = React.useState(); return ( <React.Fragment> {categories.length > 0 ? ( categories.map((category, i) => { return ( <button key={i} onClick={() => setCatName(category.name)}> {category.name} </button> ); }) ) : ( <p>Loading...</p> )} <div> {catName && categories .find((category) => category.name === catName) .posts.map((post) => <div key={post.id}>{post.name}</div>)} </div> </React.Fragment> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<Main />, rootElement);
<script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root" />
評論后更新
如果您要獲取相關的posts
數據,那么您可以useEffect
使用useEffect
。 我正在模仿下面的 API 請求。 您可以根據此調整您的代碼。
const categoriesData = [ { name: "books" }, { name: "movies" } ]; const postsData = { books: [ { id: 1, name: "foo" }, { id: 2, name: "bar" } ], movies: [ { id: 1, name: "fizz" }, { id: 2, name: "buzz" } ] }; function fakePostsApi(catName) { return new Promise((resolve) => setTimeout(() => { resolve(postsData[catName]); }, 1000) ); } function Main() { const [categories, setCategories] = React.useState(categoriesData); const [catName, setCatName] = React.useState(); const [posts, setPosts] = React.useState([]); React.useEffect(() => { if (catName) { fakePostsApi(catName) .then(setPosts); } }, [catName]); return ( <div> {categories.length > 0 ? ( categories.map((category, i) => { return ( <button key={i} onClick={() => setCatName(category.name)}> {category.name} </button> ); }) ) : ( <p>Loading...</p> )} <div> {posts.length === 0 ? ( <p>No posts...</p> ) : ( posts.map((post) => <div key={post.id}>{post.name}</div>) )} </div> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<Main />, rootElement);
<script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root" />
您可以以任何您喜歡的方式改進代碼。 例如,可能是loading
狀態並根據此顯示“更新帖子”消息。 這只是一個例子,只是為了給你一個想法。
第二次更新
您將像處理categories
一樣發出提取請求。 如果您使用類別 id 而不是名稱進行請求,那么您可以根據此更改我的示例。 取代具有的catName
狀態,您將使用catId
狀態,並保持一個類別ID那里。 我只提供相關部分:
function Main() {
const [categories, setCategories] = React.useState(categoriesData);
const [catId, setCatId] = React.useState();
const [posts, setPosts] = React.useState([]);
React.useEffect(() => {
if (catId) {
fetch(`${state.source.api}/wp/v2/posts?categories=${category.id}`)
.then((response) => response.json())
.then((data) => {
setPosts(data);
});
}
}, [catId]);
當然,您應該像這樣在onCLick
按鈕中設置類別 ID:
<button key={i} onClick={() => setCatId(category.id)}>
{category.name}
</button>
如果我理解正確,您正在尋找一種從端點構建數據的方法,然后創建一個用戶界面,用戶可以在其中顯示/隱藏基於標簽或類別的內容。
下面是一些數據和 UI 的示例,它們可以作為您正在尋找的模型。 您可能需要以類似的格式構建數據,以利用當前函數存儲數據和響應用戶輸入的方式。 如果您可以控制端點,則可以相應地重構數據。 或者,如果您不控制端點,則可以創建一個函數來根據需要對其進行結構化。 最后,您始終可以根據需要調整此模型以適合您的數據。
CodeSandbox: https ://codesandbox.io/s/stack-63862326-library-t1xx7
import React, { useState } from "react";
import styled from "styled-components";
// here is some example data that you should strive to construct if
// you happen to have control over your endpoint; otherwise you can
// reconstruct your data in a way that looks closer to this format
const exampleAPIDat = [
{
name: "Harry Potter",
category: "fantasy",
thumbnail:
"https://images-na.ssl-images-amazon.com/images/I/81YOuOGFCJL.jpg"
},
{
name: "Gardens of the Moon",
category: "fantasy",
thumbnail:
"https://vignette.wikia.nocookie.net/malazan/images/6/67/GoTM_UK_AR.jpg/revision/latest?cb=20080327022138"
},
{
name: "Use of Weapons",
category: "Sci-Fi",
thumbnail: "https://m.media-amazon.com/images/I/51NfClNMlhL.jpg"
},
{
name: "Dune",
category: "Sci-Fi",
thumbnail: "https://m.media-amazon.com/images/I/41UZeCEKOBL.jpg"
}
];
export default function App() {
const [data, setData] = useState(exampleAPIDat);
const [filter, setFilter] = useState([]);
const filterFun = (event) => {
// (1) update your filter array
// category is passed from button
let filtering = event.target.value;
var newFilter;
if (filter.includes(filtering)) {
// remove if already in filter
newFilter = [...filter].filter((f) => f !== filtering);
} else {
// add if not in the filter
newFilter = [...filter, filtering];
}
setFilter(newFilter);
// (2) update your data accordingly
let newDat = exampleAPIDat.filter(
(book) => !newFilter.includes(book.category)
);
setData(newDat);
};
const FilterButtons = ({ books }) => {
// filter the data down to just categories
let set = books.map((book) => book.category);
let categories = [...new Set(set)];
// produce a button for each category in the dat
let btns = categories.map((category, index) => (
<button key={category + index} value={category} onClick={filterFun}>
{category}
</button>
));
return btns;
};
const AvailableBooks = ({ books }) =>
books.map((book, index) => (
<BookTile key={book.name + index} background={book.thumbnail}>
<h3>{book.name}</h3>
<h5>{book.category}</h5>
</BookTile>
));
return (
<div>
<ControlRow>
<FilterButtons books={exampleAPIDat} />
</ControlRow>
<Library>
<AvailableBooks books={data} />
</Library>
</div>
);
}
const ControlRow = styled.div`
display: flex;
flex-direction: row;
& button {
margin: 16px;
}
`;
const Library = styled.div`
display: flex;
flex-flow: row wrap;
`;
const BookTile = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-end;
width: 200px;
height: 400px;
margin: 20px;
background-image: linear-gradient(
to top,
rgba(255, 255, 255, 1),
rgba(255, 255, 255, 0)
),
url(${(props) => props.background});
background-repeat: no-repeat;
background-position: center;
background-size: 200px 400px;
-webkit-box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
-moz-box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
&:hover {
transform: scale(1.1);
}
& h3 {
background-color: white;
color: green;
}
& h5 {
background-color: black;
color: white;
}
`;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.