Пагинация для рельсов API и реагирования API - PullRequest
0 голосов
/ 11 сентября 2018

Я создаю веб-приложение. Для этого я использую rails в качестве API для backend. Также используя react для frontend. У меня есть модель user. Я хотел бы отобразить все users вместе с его деталями для пользователей сайта. Так что у меня около 10000+ пользователей. Поэтому я не могу отправить всех пользователей сразу на внешний интерфейс. Я хотел бы отображать только 50 пользователей одновременно. Поэтому, чтобы увидеть следующие 50 пользователей, веб-интерфейс отправит мне новый запрос на получение следующих 50 пользователей и так далее. Поэтому я не понимаю правильный путь, как его построить.

Теперь я собираю всех таких пользователей, и мой сервер зависает.

мой users_controller.rb

 class UsersController < ApplicationController
    def index
      users = User.all
      render_success(:ok, users, meta: { message: 'User sucessfully send' })
    end
 end

Вкратце - я хочу отправлять только ограниченное количество данных во внешний интерфейс в каждом запросе.

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Вы можете использовать limit и offset, вот пример , он довольно прост и не требует каких-либо библиотек:

код рельсов:

# app/controllers/users_controller.rb
def users
  users = User.limit(params[:limit]).offset(params[:offset])
  render json: { users: users }
end

код реагирования:

const PER_PAGE = 50  // How much users to load
export default class Users extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      offset: 0,
      limit: PER_PAGE,
      users: []
    }
    this.handlePageClickNext = this.handlePageClickNext.bind(this)
    this.handlePageClickPrev = this.handlePageClickPrev.bind(this)
  }
  loadUsersFromServer() {
    fetch(`/users?limit=${this.state.limit}&offset=${this.state.offset}`)
      .then(response => response.json()).then(response => {
      this.setState({ users: response.users })
    })
  }
  handlePageClickPrev() {
    // Load prev 10 users
    let offset = this.state.offset - PER_PAGE
    if (offset < 0) return 
    this.setState({offset: offset}, () => {
      this.loadUsersFromServer();
    });
  };
  handlePageClickNext() {
    // Load next 10 users
    let offset = this.state.offset + PER_PAGE
    if (offset >= this.state.total) return

    this.setState({offset: offset}, () => {
      this.loadUsersFromServer();
    });
  };
  componentDidMount() {
    // Load users on start
    this.loadUsersFromServer();
  }
  render() {
     const users = this.state.users.map((u)=> {
       return <li>{u.id}</li>
     })

    return (
     <div>
       <ul>
        {users}
       </ul>
       <button onClick={this.handlePageClickPrev}>Prev</button>
       <button onClick={this.handlePageClickNext}>Next</button>
     </div>
   );
  }
}
0 голосов
/ 11 сентября 2018

Вы можете использовать gem 'kaminari' для разбивки на страницы в рельсах.
Выборка пользователей на основе номера страницы:

class UsersController < ApplicationController
def index
  per_page = PAGINATION[:users] # you can define it in app_config.yml  
  users = User.page(params[:page]).per(per_page)
  render json: { user_list: users, per_page: per_page, user_count: users.count, success: true }, status: :ok
end

end

В реакции вы можете использовать react-paginate для рендерингапагинационный блок.

Вы можете отобразить это на экране индекса пользователя

    renderPaginateBlock = () => {
    const { user_count, per_page } = this.props;
    if (user_count > per_page) {
      return (
        <div align='center'>
          <ReactPaginate
            previousLabel={"<"} nextLabel={">"} marginPagesDisplayed={2}
            pageRangeDisplayed={5} pageCount={this.props.user_count/this.props.per_page}
            onPageChange={(data) => this.getUserWithPagination(data.selected + 1)}
            containerClassName={"pagination custom"} subContainerClassName={"pages pagination"}
            activeClassName={"active"}
          />
        </div>
      );
    }
    else {
      return null;
    }
  }

Это установить current_page и получить доступ к API:

getUserWithPagination = (activePageNo) => {
    const { fetchUsers } = this.props;
    fetchUsers(activePageNo)
  }
0 голосов
/ 11 сентября 2018

Я не знаю, может ли это помочь вам. Но вы можете использовать камень will_paginate,

gem 'will_paginate'
gem 'bootstrap-will_paginate'

в вашей индексной функции используйте

@users = User.paginate(page: params[:page], per_page: 50)

Используя это, вы получите всех пользователей, отправленных в одном запросе и разбитых на страницы

...