簡體   English   中英

通過 WordPress REST API 循環瀏覽帖子類別 - React

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM