Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2017
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.28 KB | None | 0 0
  1. // React Infinite Scrolling Decorated Component
  2.  
  3. import React, { PropTypes } from 'react';
  4. import _ from 'lodash';
  5. import $ from 'jquery';
  6.  
  7. function getDisplayName(Component) {
  8. return Component.displayName || Component.name || 'Component';
  9. }
  10.  
  11. export default function(options = {}) {
  12. const propName = options.propName;
  13. const modelName = options.modelName;
  14.  
  15. if (!propName) {
  16. throw new Error('propName is required');
  17. }
  18.  
  19. if (!modelName) {
  20. throw new Error('modelName is required');
  21. }
  22.  
  23. return function(DecoratedComponent) {
  24. const displayName = 'InfiniteScrolling(' + getDisplayName(DecoratedComponent) + ')';
  25.  
  26. return React.createClass({
  27. displayName: displayName,
  28.  
  29. contextTypes: {
  30. store: PropTypes.object.isRequired
  31. },
  32.  
  33. getInitialState: function() {
  34. return {
  35. pages: [
  36. this.props[propName]
  37. ]
  38. };
  39. },
  40.  
  41. componentDidMount: function() {
  42. window.addEventListener('scroll', this.onPageScroll);
  43. },
  44.  
  45. componentWillUnmount: function() {
  46. window.removeEventListener('scroll', this.onPageScroll);
  47. },
  48.  
  49. onPageScroll() {
  50. const storeState = this.context.store.getState();
  51. const pages = this.state.pages;
  52. const firstPage = pages[0];
  53. const lastPage = pages[pages.length - 1];
  54. const nextPageNumber = Number(lastPage.query.pagination.page) + 1;
  55. const totalPage = firstPage.meta.totalPage;
  56.  
  57. var isScrollAtBottom = (window.innerHeight + window.scrollY) == $(document).height();
  58.  
  59. if (isScrollAtBottom && nextPageNumber <= totalPage) {
  60. this.onLoadMore();
  61. }
  62. },
  63.  
  64. componentWillReceiveProps: function(nextProps) {
  65. const storeState = this.context.store.getState();
  66. const pages = this.state.pages;
  67.  
  68. // Whenever the component re-renders, we need to rebuild our collection of pages
  69. // by fetching them back out of the Store. If we don't do this, our state data
  70. // will always be stale - we'll never know when data finishes being fetched, and
  71. // in the cases where some of the data is being modified, such as being updated
  72. // or deleted, we won't get a change to react to those changes and inform the user.
  73. let nextPages = pages.map(function(page) {
  74. const query = JSON.stringify(page.query);
  75. return storeState[modelName].find[query];
  76. });
  77.  
  78. const currentQuery = JSON.stringify(this.props[propName].query.where);
  79. const nextQuery = JSON.stringify(nextProps[propName].query.where);
  80.  
  81. if (currentQuery !== nextQuery) {
  82. nextPages = [
  83. nextProps[propName]
  84. ];
  85. }
  86.  
  87. this.setState({
  88. pages: nextPages
  89. });
  90. },
  91.  
  92. onLoadMore: function() {
  93. const storeState = this.context.store.getState();
  94. const pages = this.state.pages;
  95. const lastPage = pages[pages.length - 1];
  96. const nextPageNumber = Number(lastPage.query.pagination.page) + 1;
  97. const query = lastPage.query;
  98.  
  99. // Build the next page's query from the previous page. The only
  100. // thing we're changing is the page of data we want to fetch
  101. const nextQuery = {
  102. where: query.where,
  103. pagination: _.defaults({
  104. page: nextPageNumber
  105. }, query.pagination)
  106. };
  107.  
  108. // See if the next page has already been fetched, and used the cached page
  109. // if available
  110. let nextPage = storeState[modelName].find[JSON.stringify(nextQuery)];
  111.  
  112. if (!nextPage) {
  113. // The 'find' action has a slightly different interface than the 'getState' call
  114. // in 'lore.connect'. When calling the 'find' action directly, you need to pass
  115. // in the 'where' clause and the 'pagination' information as different arguments,
  116. // like 'lore.actions.tweet.find(where, pagination)'
  117. nextPage = lore.actions[modelName].find(nextQuery.where, nextQuery.pagination).payload;
  118. }
  119.  
  120. pages.push(nextPage);
  121.  
  122. this.setState({
  123. pages: pages
  124. });
  125. },
  126.  
  127. render: function() {
  128. return React.createElement(
  129. DecoratedComponent,
  130. _.assign({ref: 'decoratedComponent'}, this.state, this.props, { onLoadMore: this.onLoadMore })
  131. );
  132. }
  133. });
  134. }
  135. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement