Я хочу реализовать кнопку «Загрузить больше» на моем следующем сайте JS

  1. Мы создали наш блог на Next JS, используя WordPress в качестве нашего API, мы добавляли контент, пока не превысили 500, и наш блог продолжал зависать, потому что нам приходилось вызывать все сообщения нашего блога одновременно с сервера.

  2. Мы намерены создать функцию кнопки разбивки на страницы «Загрузить больше», которая при нажатии вызывает только определенное количество объектов за раз.

Вот как выглядит наш код.

  1. Индекс блога

//index.tsx

/**
 * Caution: Consider this file when using NextJS or GatsbyJS
 *
 * You may delete this file and its occurrences from the project filesystem if you are using react-scripts
 */
import React from 'react';
import BlogSearch from 'views/BlogSearch';
import Main from 'layouts/Main';
import WithLayout from 'WithLayout';
import Head from 'next/head';
import { getBlogPosts } from '../../lib/api';

const BlogPage = ({ posts }): JSX.Element => {
  return (
    <>
      {' '}
      <Head>
        <title>Copy and Post - Blog</title>
        <meta
          property = "og:title"
          content = "Copy and Post - Blog"
          key = "Copy and Post"
        />
      </Head>
      <WithLayout
        component = {() => <BlogSearch posts = {posts} />}
        layout = {Main}
      />
    </>
  );
};

export default BlogPage;

export async function getStaticProps() {
  
  const posts = await getBlogPosts();

  return {
    props: {
      ...posts,
   

    },
  };
}





  1. Наш функционал API.
//api.ts

import { homepageQuery, blogPosts, blogPostBySlug } from './queries';

const API_URL = process.env.WP_API_URL;

async function fetchAPI(query, { variables = {} } = {}) {
  // Set up some headers to tell the fetch call
  // that this is an application/json type
  const headers = { 'Content-Type': 'application/json' };

  // build out the fetch() call using the API_URL
  // environment variable pulled in at the start
  // Note the merging of the query and variables
  const res = await fetch(API_URL, {
    method: 'POST',
    headers,
    body: JSON.stringify({ query, variables }),
  });

  // error handling work
  const json = await res.json();
  if (json.errors) {
    console.info(json.errors);
    console.info('error details', query, variables);
    throw new Error('Failed to fetch API');
  }
  return json.data;
}

export async function getHomepageSections() {
  const data = await fetchAPI(homepageQuery);
  return data;
}

export async function getBlogPosts() {
  const data = await fetchAPI(blogPosts);
  return data;
}

export async function getBlogPostBySlug(slug) {
  const data = await fetchAPI(blogPostBySlug, { variables: { id: slug } });
  return data;
}



  1. Наконец, наша функция запроса.

//query.ts


export const homepageQuery = `
query HomepageQuery {
    homepageSections {
      edges {
        node {
          homepage {
            hero {
              animatedwords
              heading
              subtitle
            }
            callouts {
              title
              subtitle
              calloutone {
                title
                subtext
                image {
                  mediaItemUrl
                }
              }
              calloutthree {
                title
                subtext
                image {
                  mediaItemUrl
                }
              }
              callouttwo {
                title
                subtext
                image {
                  mediaItemUrl
                }
              }
            }
            icongrid {
              iconone {
                description
                icon
                title
              }
              iconfive {
                description
                icon
                title
              }
              iconfour {
                description
                icon
                title
              }
              iconsix {
                description
                icon
                title
              }
              iconthree {
                description
                icon
                title
              }
              icontwo {
                description
                icon
                title
              }
            }
          }
        }
      }
    }
  } 
`;

export const blogPosts = `
  query BlogPosts {
    posts(first: 1000) {
      edges {
        node {
          author {
            node {
              nickname
            }
          }
          date
          slug
          featuredImage {
            node {
              mediaItemUrl
            }
          }
          title
        }
      }
    }
  }
`;

export const blogPostBySlug = `
  query PostBySlug($id: ID!) {
    post(id: $id, idType: SLUG) {
      id
      content
      title
      author {
        node {
          nickname
          avatar {
            url
          }
        }
      }
      date
      featuredImage {
        node {
          mediaItemUrl
        }
      }
    }
  }
`;

  1. Вот как выглядит наша консоль.

🤔 А знаете ли вы, что...
С React можно легко интегрировать с существующими проектами и кодом.


285
3

Ответы:

Реализация нумерации страниц по принципу «загрузи больше» — непростая задача. Я просто дам базовый обзор того, как это можно реализовать как на стороне клиента, так и на стороне сервера.

Серверная часть

У вас должна быть конечная точка API, которая принимает параметры limit и startAfter. по умолчанию, когда пользователь запрашивает без параметров startAfter, возвращаются блоги в качестве ограничения.

если параметр startAfter доступен, отправьте в блоги те идентификаторы, которые идут после значения startAfter.

/blogs?limit=10 => return top 10 blogs
/blogs?limit=10&startAfter=10 => return next 10 blogs (where 10 is last blog id)

Сторона клиента

На стороне клиента извлеките несколько начальных блогов с помощью функции getStaticProps, а затем всякий раз, когда пользователь завершает прокрутку или нажимает кнопку «Загрузить еще», извлекайте новые блоги, отправляя параметр startAfter. прекратите запрашивать, если сервер отправляет обратно пустой массив.

export default function Blogs({ posts }) {
    const [blogs, setBlogs] = useState(posts)
    
    const loadMorePost = useCallback(() => {
       const makeReq = async ()=> {
           const res = await fetch(`/blogs?limit=10&startAt=${blogs.at(-1).id}`)
           const json = await res.json()
           // TODO: stop fetching if response is empty array
           setBlogs(blogs => [...json, blogs])
       }
    }, [blogs])
    
    return <> 
      {/* ... */}
      <button onClick = {loadMorePost}>load more</button>
    </>

}

Приложение

для справки вы можете проверить, как я реализовал нумерацию страниц в своем приложении.


Решено

Я думаю, вы можете использовать смещение и ограничение в качестве переменных для вашего внутреннего запроса. что-то вроде этого (не уверен, называется ли это offset или startAfter):

posts(offset: $offset, limit: $limit) {

и внутреннюю функцию API следует изменить, чтобы разрешить эти параметры.

export async function getBlogPosts(offset, limit) {
    const data = await fetchAPI(blogPosts, { variables: { offset, limit} });
    return data;
 }

и сохраните текущую страницу на стороне клиента. на стороне клиента, если вы нажмете кнопку «Загрузить больше», вы можете выполнить расчет лимитов следующим образом:

const PAGE_SIZE = 100
let current_page = 0

export async function getStaticProps() {
    current_page += 1
    const offset = PAGE_SIZE * current_page
    const limit = offset + PAGE_SIZE 

    const posts = await getBlogPosts(offset, limit );

    return ...

Спасибо всем за ваши предложения, но вот как я наконец решил эту проблему.

  1. Я отредактировал запрос, включив в него некоторые параметры.

# queries.ts


let condition = `after: "${endCursor}",first: 12, where: {orderby: {field: DATE, order: DESC}}`
export const blogPosts = `
  query BlogPosts {
    posts(${condition}) {
      edges {
        node {
          author {
            node {
              nickname
            }
          }
          date
          slug
          featuredImage {
            node {
              mediaItemUrl
            }
          }
          title
        }
      }

      pageInfo {
        endCursor
        hasNextPage
        hasPreviousPage
        startCursor
      }
    }
  }
`;

  1. Затем я настроил API так, чтобы оно выглядело следующим образом.
Api.ts

export async function getBlogPosts(endCursor = null, taxonomy = null) {
  const data = await fetchAPI(blogPosts);
  return data;
}

  1. Наконец я создал компонент «Загрузить еще».
#LoadMore.ts


import React from 'react';
import { getBlogPosts } from '../../../../lib/api';


const LoadMore = ({posts, setPosts}) => {

    const handleOnclick = async(event) =>{
  
          const morePosts = await getBlogPosts(posts.pageInfo.endCursor)
  
          let updatedPosts = {
            pageInfo: {
  
            },
            nodes: []
        }
          updatedPosts.pageInfo = morePosts.pageInfo;
  
            posts.nodes.map((node) => {
                  updatedPosts.nodes.push(node);
              });
  
          morePosts.nodes.map((node) => {
                updatedPosts.nodes.push(node);
            });
  
        setPosts(updatedPosts);
  
  
    }
    return (
      <>
       <button
       
       onClick = {handleOnclick}
       >
        Load More
       </button>
      </>
    );
  };
  

  export default LoadMore;

Для получения дополнительной информации мне помогли с этим видео на YouTube.

https://thewikihow.com/video_HI_tZRIfhIw&list=PLHYTWh7vcn_D36jk_L93NTOb0B5sqgjxX&index=3&t=1167s