From c246a1deaec85254a421e014e974006272dc1b2b Mon Sep 17 00:00:00 2001 From: Chau Duong Date: Sun, 14 Jan 2018 15:42:41 +0700 Subject: [PATCH 1/3] perf: Cache posts in redux store or performance --- src/App.js | 2 +- src/components/Common/Sort/Sort.js | 7 +-- src/components/ForYou/ForYou.js | 73 +++++++++++------------- src/components/Home/Home.js | 92 ++++++++++++++++-------------- src/components/Home/Home.render.js | 2 +- src/components/Saved/Saved.js | 73 +++++++++++------------- src/state/ducks/index.js | 1 + src/state/ducks/posts/actions.js | 86 ++++++++++++++++++++++++++++ src/state/ducks/posts/index.js | 15 +++++ src/state/ducks/posts/reducers.js | 41 +++++++++++++ src/state/ducks/posts/selectors.js | 37 ++++++++++++ src/state/ducks/posts/types.js | 11 ++++ 12 files changed, 307 insertions(+), 133 deletions(-) create mode 100644 src/state/ducks/posts/actions.js create mode 100644 src/state/ducks/posts/index.js create mode 100644 src/state/ducks/posts/reducers.js create mode 100644 src/state/ducks/posts/selectors.js create mode 100644 src/state/ducks/posts/types.js diff --git a/src/App.js b/src/App.js index 2bf11ed..0be4fb9 100644 --- a/src/App.js +++ b/src/App.js @@ -28,7 +28,7 @@ const routes = [{ render: HomeRender, }, { key: 'source', - path: '/source/:source', + path: '/source/:sourceId', render: HomeRender, }, { key: 'for-you', diff --git a/src/components/Common/Sort/Sort.js b/src/components/Common/Sort/Sort.js index a95cb6c..e9b0fa4 100644 --- a/src/components/Common/Sort/Sort.js +++ b/src/components/Common/Sort/Sort.js @@ -6,19 +6,15 @@ import './Sort.scss'; const propTypes = { current: PropTypes.string.isRequired, - onClick: PropTypes.func.isRequired, }; -const Sort = ({ current, onClick }) => { +const Sort = ({ current }) => { const items = [{ display: 'New', value: 'new', }, { display: 'Best', value: 'best', - // }, { - // display: 'Daily', - // value: 'daily', }]; return ( @@ -30,7 +26,6 @@ const Sort = ({ current, onClick }) => { to={{ search: `?sort=${value}`, }} - onClick={() => onClick(value)} >{display} ))} diff --git a/src/components/ForYou/ForYou.js b/src/components/ForYou/ForYou.js index 6a7807a..6c7f571 100644 --- a/src/components/ForYou/ForYou.js +++ b/src/components/ForYou/ForYou.js @@ -1,7 +1,10 @@ import React, { Component } from 'react'; -import { Users } from '@gorillab/reader-js'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; import qs from 'qs'; +import { getForYouPosts, postsSelectors } from '../../state/ducks/posts'; + import PageHeader from '../Common/PageHeader'; import PageTitle from '../Common/PageTitle'; import Sort from '../Common/Sort'; @@ -12,6 +15,11 @@ import './ForYou.scss'; const LIMIT = 25; +const propTypes = { + getPosts: PropTypes.func.isRequired, + getForYouPosts: PropTypes.func.isRequired, +}; + class ForYou extends Component { constructor(props) { super(props); @@ -26,52 +34,28 @@ class ForYou extends Component { }; this.getMore = this.getMore.bind(this); - this.changeSort = this.changeSort.bind(this); - } - - componentDidMount() { - this.getPosts(); } - async getPosts(query = {}) { - try { - const posts = await Users.getForYou({ + async componentDidMount() { + if (!this.props.getPosts(this.state.sort).length) { + await this.props.getForYouPosts({ sort: this.state.sort, limit: this.state.limit, page: this.state.page, - ...query, }); - - this.setState({ - posts, - ...query, - }); - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); } + // eslint-disable-next-line react/no-did-mount-set-state + this.setState({ + posts: [...this.props.getPosts(this.state.sort)], + }); } - async getMore() { - try { - const posts = await Users.getForYou({ - sort: this.state.sort, - limit: LIMIT, - page: Math.floor(this.state.posts.length / LIMIT) + 1, - }); - - this.setState({ - posts: this.state.posts.concat(posts), - limit: this.state.limit + LIMIT, - }); - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); - } - } - - changeSort(sort) { - this.getPosts({ sort }); + getMore() { + this.props.getForYouPosts({ + sort: this.state.sort, + limit: LIMIT, + page: Math.floor(this.props.getPosts(this.state.sort).length / LIMIT) + 1, + }); } render() { @@ -80,7 +64,7 @@ class ForYou extends Component { - + @@ -95,5 +79,12 @@ class ForYou extends Component { ); } } - -export default ForYou; +ForYou.propTypes = propTypes; + +export default connect( + state => ({ + getPosts: postsSelectors.getForYouPosts(state), + }), { + getForYouPosts, + }, +)(ForYou); diff --git a/src/components/Home/Home.js b/src/components/Home/Home.js index 92bf9c2..0cb7207 100644 --- a/src/components/Home/Home.js +++ b/src/components/Home/Home.js @@ -1,8 +1,10 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { Posts } from '@gorillab/reader-js'; +import { connect } from 'react-redux'; import qs from 'qs'; +import { getHomePosts, getSourcePosts, postsSelectors } from '../../state/ducks/posts'; + import PageHeader from '../Common/PageHeader'; import PageTitle from '../Common/PageTitle'; import Sort from '../Common/Sort'; @@ -18,6 +20,12 @@ const propTypes = { isLoggedIn: PropTypes.bool.isRequired, title: PropTypes.string.isRequired, source: PropTypes.any, + getPosts: PropTypes.func.isRequired, + getHomePosts: PropTypes.func.isRequired, + // eslint-disable-next-line react/no-unused-prop-types + getPostsBySource: PropTypes.func.isRequired, + // eslint-disable-next-line react/no-unused-prop-types + match: PropTypes.any.isRequired, }; const defaultProps = { source: undefined, @@ -28,7 +36,6 @@ class Home extends Component { super(props); const { sort } = qs.parse(location.search, { ignoreQueryPrefix: true }); - this.state = { posts: [], sort: sort || 'new', @@ -37,54 +44,45 @@ class Home extends Component { }; this.getMore = this.getMore.bind(this); - this.changeSort = this.changeSort.bind(this); - } - - componentDidMount() { - this.getPosts(); } - async getPosts(query = {}) { - try { - const posts = await Posts.getPosts({ - source: this.props.source ? this.props.source.id : undefined, - sort: this.state.sort, - limit: this.state.limit, - page: this.state.page, - ...query, - }); - + async componentDidMount() { + const sourceId = this.props.match.params.sourceId; + if (sourceId) { + if (!this.props.getPostsBySource(this.state.sort, sourceId).length) { + await this.props.getSourcePosts({ + source: sourceId, + sort: this.state.sort, + limit: this.state.limit, + page: this.state.page, + }); + } + // eslint-disable-next-line react/no-did-mount-set-state this.setState({ - posts, - ...query, + posts: [...this.props.getPostsBySource(this.state.sort, sourceId)], }); - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); - } - } - - async getMore() { - try { - const posts = await Posts.getPosts({ - source: this.props.source ? this.props.source.id : undefined, - sort: this.state.sort, - limit: LIMIT, - page: Math.floor(this.state.posts.length / LIMIT) + 1, - }); - + } else { + if (!this.props.getPosts(this.state.sort).length) { + await this.props.getHomePosts({ + sort: this.state.sort, + limit: this.state.limit, + page: this.state.page, + }); + } + // eslint-disable-next-line react/no-did-mount-set-state this.setState({ - posts: this.state.posts.concat(posts), - limit: this.state.limit + LIMIT, + posts: [...this.props.getPosts(this.state.sort)], }); - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); } } - changeSort(sort) { - this.getPosts({ sort }); + getMore() { + this.props.getHomePosts({ + source: this.props.source ? this.props.source.id : undefined, + sort: this.state.sort, + limit: LIMIT, + page: Math.floor(this.props.getPosts(this.state.sort).length / LIMIT) + 1, + }); } render() { @@ -96,7 +94,7 @@ class Home extends Component { {this.props.isLoggedIn && this.props.source && } - + @@ -115,4 +113,12 @@ class Home extends Component { Home.propTypes = propTypes; Home.defaultProps = defaultProps; -export default Home; +export default connect( + state => ({ + getPosts: postsSelectors.getHomePosts(state), + getPostsBySource: postsSelectors.getSourcePosts(state), + }), { + getHomePosts, + getSourcePosts, + }, +)(Home); diff --git a/src/components/Home/Home.render.js b/src/components/Home/Home.render.js index 55acfc9..705270f 100644 --- a/src/components/Home/Home.render.js +++ b/src/components/Home/Home.render.js @@ -17,7 +17,7 @@ const HomeRender = ({ match, getSource, ...rest }) => { const source = match.params.source ? getSource(match.params.source) : undefined; const title = source ? source.title : 'Explore'; - return ; + return ; }; HomeRender.propTypes = propTypes; diff --git a/src/components/Saved/Saved.js b/src/components/Saved/Saved.js index dfef54e..6bc0e6c 100644 --- a/src/components/Saved/Saved.js +++ b/src/components/Saved/Saved.js @@ -1,7 +1,10 @@ import React, { Component } from 'react'; -import { Users } from '@gorillab/reader-js'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; import qs from 'qs'; +import { getSavedPosts, postsSelectors } from '../../state/ducks/posts'; + import PageHeader from '../Common/PageHeader'; import PageTitle from '../Common/PageTitle'; import Sort from '../Common/Sort'; @@ -12,12 +15,16 @@ import './Saved.scss'; const LIMIT = 25; +const propTypes = { + getPosts: PropTypes.func.isRequired, + getSavedPosts: PropTypes.func.isRequired, +}; + class Saved extends Component { constructor(props) { super(props); const { sort } = qs.parse(location.search, { ignoreQueryPrefix: true }); - this.state = { posts: [], sort: sort || 'new', @@ -26,52 +33,28 @@ class Saved extends Component { }; this.getMore = this.getMore.bind(this); - this.changeSort = this.changeSort.bind(this); - } - - componentDidMount() { - this.getPosts(); } - async getPosts(query = {}) { - try { - const posts = await Users.getSaved({ + async componentDidMount() { + if (!this.props.getPosts(this.state.sort).length) { + await this.props.getSavedPosts({ sort: this.state.sort, limit: this.state.limit, page: this.state.page, - ...query, - }); - - this.setState({ - posts, - ...query, - }); - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); - } - } - - async getMore() { - try { - const posts = await Users.getSaved({ - sort: this.state.sort, - limit: LIMIT, - page: Math.floor(this.state.posts.length / LIMIT) + 1, }); - - this.setState({ - posts: this.state.posts.concat(posts), - limit: this.state.limit + LIMIT, - }); - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); } + // eslint-disable-next-line react/no-did-mount-set-state + this.setState({ + posts: [...this.props.getPosts(this.state.sort)], + }); } - async changeSort(sort) { - await this.getPosts({ sort }); + getMore() { + this.props.getSavedPosts({ + sort: this.state.sort, + limit: LIMIT, + page: Math.floor(this.props.getPosts(this.state.sort).length / LIMIT) + 1, + }); } render() { @@ -80,7 +63,7 @@ class Saved extends Component { - + @@ -96,4 +79,12 @@ class Saved extends Component { } } -export default Saved; +Saved.propTypes = propTypes; + +export default connect( + state => ({ + getPosts: postsSelectors.getSavedPosts(state), + }), { + getSavedPosts, + }, +)(Saved); diff --git a/src/state/ducks/index.js b/src/state/ducks/index.js index c439eed..eabbac8 100644 --- a/src/state/ducks/index.js +++ b/src/state/ducks/index.js @@ -1,2 +1,3 @@ +export { default as posts } from './posts'; export { default as sources } from './sources'; export { default as user } from './user'; diff --git a/src/state/ducks/posts/actions.js b/src/state/ducks/posts/actions.js new file mode 100644 index 0000000..777f0ba --- /dev/null +++ b/src/state/ducks/posts/actions.js @@ -0,0 +1,86 @@ +import { Posts, Users } from '@gorillab/reader-js'; + + +import { GET_HOME_POSTS, GET_FOR_YOU_POSTS, GET_SAVED_POSTS, GET_SOURCE_POSTS } from './types'; + +const getHomePosts = ({ sort = 'new', limit = 25, page = 1 }) => async (dispatch) => { + try { + const posts = await Posts.getPosts({ + limit, + page, + sort, + }); + + dispatch({ + type: GET_HOME_POSTS, + posts, + }); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } +}; + +const getForYouPosts = ({ sort = 'new', limit = 25, page = 1 }) => async (dispatch) => { + try { + const posts = await Users.getForYou({ + sort, + limit, + page, + }); + + dispatch({ + type: GET_FOR_YOU_POSTS, + posts, + }); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } +}; + +const getSavedPosts = ({ sort = 'new', limit = 25, page = 1 }) => async (dispatch) => { + try { + const posts = await Users.getSaved({ + sort, + limit, + page, + }); + + dispatch({ + type: GET_SAVED_POSTS, + posts, + }); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } +}; + +const getSourcePosts = ({ source, sort = 'new', limit = 25, page = 1 }) => async (dispatch) => { + try { + const posts = await Posts.getPosts({ + source, + limit, + page, + sort, + }); + + dispatch({ + type: GET_SOURCE_POSTS, + posts, + source, + }); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } +}; + +export { + // eslint-disable-next-line import/prefer-default-export + getHomePosts, + getForYouPosts, + getSavedPosts, + getSourcePosts, +}; diff --git a/src/state/ducks/posts/index.js b/src/state/ducks/posts/index.js new file mode 100644 index 0000000..4f8201c --- /dev/null +++ b/src/state/ducks/posts/index.js @@ -0,0 +1,15 @@ +import { getHomePosts, getForYouPosts, getSavedPosts, getSourcePosts } from './actions'; +import * as postsSelectors from './selectors'; +import postsReducers from './reducers'; + +export { + // actions + getHomePosts, + getForYouPosts, + getSavedPosts, + getSourcePosts, + // selectors + postsSelectors, +}; + +export default postsReducers; diff --git a/src/state/ducks/posts/reducers.js b/src/state/ducks/posts/reducers.js new file mode 100644 index 0000000..952a0b9 --- /dev/null +++ b/src/state/ducks/posts/reducers.js @@ -0,0 +1,41 @@ +import { GET_HOME_POSTS, GET_FOR_YOU_POSTS, GET_SAVED_POSTS, GET_SOURCE_POSTS } from './types'; + +const initialState = { + home: [], + forYou: [], + saved: [], + sources: {}, +}; + +const postsReducer = (state = initialState, action) => { + switch (action.type) { + case GET_HOME_POSTS: + return { + ...state, + home: action.posts, + }; + case GET_FOR_YOU_POSTS: + return { + ...state, + forYou: action.posts, + }; + case GET_SAVED_POSTS: + return { + ...state, + saved: action.posts, + }; + case GET_SOURCE_POSTS: + return { + ...state, + sources: { + ...state.sources, + [action.source]: action.posts, + }, + }; + + default: + return state; + } +}; + +export default postsReducer; diff --git a/src/state/ducks/posts/selectors.js b/src/state/ducks/posts/selectors.js new file mode 100644 index 0000000..e50bd20 --- /dev/null +++ b/src/state/ducks/posts/selectors.js @@ -0,0 +1,37 @@ +const sort = (posts, sortBy, source) => { + if (source && posts[source] !== undefined) { + return sortBy === 'new' ? + posts[source].sort(post => new Date(post.timestamp) - new Date()) : + posts[source].sort((postF, postS) => + (postS.meta.numViewed + postS.meta.numShared + postS.meta.numSaved) - + (postF.meta.numViewed + postF.meta.numShared + postF.meta.numSaved)); + } + return sortBy === 'new' ? + posts.sort(post => new Date(post.timestamp) - new Date()) : + posts.sort((postF, postS) => + (postS.meta.numViewed + postS.meta.numShared + postS.meta.numSaved) - + (postF.meta.numViewed + postF.meta.numShared + postF.meta.numSaved)); +}; + +const getHomePosts = state => sortBy => ( + sort(Object.values(state.posts.home), sortBy) +); + +const getForYouPosts = state => sortBy => ( + sort(Object.values(state.posts.forYou), sortBy) +); + +const getSavedPosts = state => sortBy => ( + sort(Object.values(state.posts.saved), sortBy) +); + +const getSourcePosts = state => (sortBy, source) => ( + state.posts.sources[source] ? sort(state.posts.sources, sortBy, source) : 0 +); + +export { + getHomePosts, + getForYouPosts, + getSavedPosts, + getSourcePosts, +}; diff --git a/src/state/ducks/posts/types.js b/src/state/ducks/posts/types.js new file mode 100644 index 0000000..36ec786 --- /dev/null +++ b/src/state/ducks/posts/types.js @@ -0,0 +1,11 @@ +const GET_HOME_POSTS = 'posts/GET_HOME_POSTS'; +const GET_FOR_YOU_POSTS = 'posts/GET_FOR_YOU_POSTS'; +const GET_SAVED_POSTS = 'posts/GET_SAVED_POSTS'; +const GET_SOURCE_POSTS = 'posts/GET_SOURCE_POSTS'; + +export { + GET_HOME_POSTS, + GET_FOR_YOU_POSTS, + GET_SAVED_POSTS, + GET_SOURCE_POSTS, +}; From 2556be4a3f33a9c4927ab0533c62c7c50787e387 Mon Sep 17 00:00:00 2001 From: Chau Duong Date: Sun, 14 Jan 2018 18:03:36 +0700 Subject: [PATCH 2/3] perf: Change code to improve app --- src/components/ForYou/ForYou.test.js | 11 ++++++++--- src/components/Home/Home.js | 12 +++++------- src/components/Home/Home.render.js | 4 ++-- src/components/Saved/Saved.test.js | 13 +++++++++---- src/state/ducks/posts/actions.js | 1 - src/state/ducks/posts/selectors.js | 26 +++++++------------------- 6 files changed, 31 insertions(+), 36 deletions(-) diff --git a/src/components/ForYou/ForYou.test.js b/src/components/ForYou/ForYou.test.js index 29f3693..8bbb45a 100644 --- a/src/components/ForYou/ForYou.test.js +++ b/src/components/ForYou/ForYou.test.js @@ -1,13 +1,18 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { Provider as ReduxProvider } from 'react-redux'; import { MemoryRouter } from 'react-router-dom'; import ForYou from './ForYou'; +import configureStore from '../../state'; it('renders without crashing', () => { const div = document.createElement('div'); + const store = configureStore(window.REDUX_INITIAL_DATA); ReactDOM.render( - - - , div); + + + + + , div); }); diff --git a/src/components/Home/Home.js b/src/components/Home/Home.js index 0cb7207..a1cfb31 100644 --- a/src/components/Home/Home.js +++ b/src/components/Home/Home.js @@ -19,16 +19,14 @@ const LIMIT = 25; const propTypes = { isLoggedIn: PropTypes.bool.isRequired, title: PropTypes.string.isRequired, - source: PropTypes.any, + source: PropTypes.object.isRequired, getPosts: PropTypes.func.isRequired, getHomePosts: PropTypes.func.isRequired, // eslint-disable-next-line react/no-unused-prop-types getPostsBySource: PropTypes.func.isRequired, - // eslint-disable-next-line react/no-unused-prop-types - match: PropTypes.any.isRequired, }; const defaultProps = { - source: undefined, + source: {}, }; class Home extends Component { @@ -47,9 +45,9 @@ class Home extends Component { } async componentDidMount() { - const sourceId = this.props.match.params.sourceId; + const sourceId = this.props.source.id; if (sourceId) { - if (!this.props.getPostsBySource(this.state.sort, sourceId).length) { + if (!this.props.getPostsBySource(sourceId, this.state.sort).length) { await this.props.getSourcePosts({ source: sourceId, sort: this.state.sort, @@ -59,7 +57,7 @@ class Home extends Component { } // eslint-disable-next-line react/no-did-mount-set-state this.setState({ - posts: [...this.props.getPostsBySource(this.state.sort, sourceId)], + posts: [...this.props.getPostsBySource(sourceId, this.state.sort)], }); } else { if (!this.props.getPosts(this.state.sort).length) { diff --git a/src/components/Home/Home.render.js b/src/components/Home/Home.render.js index 705270f..54c8fef 100644 --- a/src/components/Home/Home.render.js +++ b/src/components/Home/Home.render.js @@ -14,10 +14,10 @@ const propTypes = { }; const HomeRender = ({ match, getSource, ...rest }) => { - const source = match.params.source ? getSource(match.params.source) : undefined; + const source = match.params.sourceId ? getSource(match.params.sourceId) : undefined; const title = source ? source.title : 'Explore'; - return ; + return ; }; HomeRender.propTypes = propTypes; diff --git a/src/components/Saved/Saved.test.js b/src/components/Saved/Saved.test.js index 6e4f661..3c8af2c 100644 --- a/src/components/Saved/Saved.test.js +++ b/src/components/Saved/Saved.test.js @@ -1,13 +1,18 @@ import React from 'react'; import ReactDOM from 'react-dom'; - +import { Provider as ReduxProvider } from 'react-redux'; import { MemoryRouter } from 'react-router-dom'; + import Saved from './Saved'; +import configureStore from '../../state'; it('renders without crashing', () => { const div = document.createElement('div'); + const store = configureStore(window.REDUX_INITIAL_DATA); ReactDOM.render( - - - , div); + + + + + , div); }); diff --git a/src/state/ducks/posts/actions.js b/src/state/ducks/posts/actions.js index 777f0ba..f7337b3 100644 --- a/src/state/ducks/posts/actions.js +++ b/src/state/ducks/posts/actions.js @@ -78,7 +78,6 @@ const getSourcePosts = ({ source, sort = 'new', limit = 25, page = 1 }) => async }; export { - // eslint-disable-next-line import/prefer-default-export getHomePosts, getForYouPosts, getSavedPosts, diff --git a/src/state/ducks/posts/selectors.js b/src/state/ducks/posts/selectors.js index e50bd20..7f12a50 100644 --- a/src/state/ducks/posts/selectors.js +++ b/src/state/ducks/posts/selectors.js @@ -1,11 +1,5 @@ -const sort = (posts, sortBy, source) => { - if (source && posts[source] !== undefined) { - return sortBy === 'new' ? - posts[source].sort(post => new Date(post.timestamp) - new Date()) : - posts[source].sort((postF, postS) => - (postS.meta.numViewed + postS.meta.numShared + postS.meta.numSaved) - - (postF.meta.numViewed + postF.meta.numShared + postF.meta.numSaved)); - } +// eslint-disable-next-line arrow-body-style +const sort = (posts, sortBy) => { return sortBy === 'new' ? posts.sort(post => new Date(post.timestamp) - new Date()) : posts.sort((postF, postS) => @@ -13,20 +7,14 @@ const sort = (posts, sortBy, source) => { (postF.meta.numViewed + postF.meta.numShared + postF.meta.numSaved)); }; -const getHomePosts = state => sortBy => ( - sort(Object.values(state.posts.home), sortBy) -); +const getHomePosts = state => sortBy => (sort(Object.values(state.posts.home), sortBy)); -const getForYouPosts = state => sortBy => ( - sort(Object.values(state.posts.forYou), sortBy) -); +const getForYouPosts = state => sortBy => (sort(Object.values(state.posts.forYou), sortBy)); -const getSavedPosts = state => sortBy => ( - sort(Object.values(state.posts.saved), sortBy) -); +const getSavedPosts = state => sortBy => (sort(Object.values(state.posts.saved), sortBy)); -const getSourcePosts = state => (sortBy, source) => ( - state.posts.sources[source] ? sort(state.posts.sources, sortBy, source) : 0 +const getSourcePosts = state => (source, sortBy) => ( + sort(state.posts.sources[source] || [], sortBy) ); export { From 2b745d9a098a0fc5535a76285f9c18abb1db6e5e Mon Sep 17 00:00:00 2001 From: Chau Duong Date: Sat, 10 Feb 2018 13:54:21 +0700 Subject: [PATCH 3/3] fix: In progress --- src/components/Home/Home.js | 24 ++++++++++++++++++++---- src/components/Posts/PostsList.js | 1 - src/state/ducks/posts/reducers.js | 5 ++--- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/components/Home/Home.js b/src/components/Home/Home.js index a1cfb31..0f0dcc3 100644 --- a/src/components/Home/Home.js +++ b/src/components/Home/Home.js @@ -19,8 +19,9 @@ const LIMIT = 25; const propTypes = { isLoggedIn: PropTypes.bool.isRequired, title: PropTypes.string.isRequired, - source: PropTypes.object.isRequired, + source: PropTypes.any, getPosts: PropTypes.func.isRequired, + // eslint-disable-next-line react/no-unused-prop-types getHomePosts: PropTypes.func.isRequired, // eslint-disable-next-line react/no-unused-prop-types getPostsBySource: PropTypes.func.isRequired, @@ -74,12 +75,27 @@ class Home extends Component { } } - getMore() { - this.props.getHomePosts({ + async getMore() { + if (this.props.source) { + await this.props.getSourcePosts({ + source: this.props.source.id, + sort: this.state.sort, + limit: this.state.limit, + page: Math.floor(this.state.posts.length / LIMIT) + 1, + }); + this.setState({ + posts: [...this.props.getPostsBySource(this.props.source.id, this.state.sort)], + }); + return; + } + await this.props.getHomePosts({ source: this.props.source ? this.props.source.id : undefined, sort: this.state.sort, limit: LIMIT, - page: Math.floor(this.props.getPosts(this.state.sort).length / LIMIT) + 1, + page: Math.floor(this.state.posts.length / LIMIT) + 1, + }); + this.setState({ + posts: [...this.props.getPosts(this.state.sort)], }); } diff --git a/src/components/Posts/PostsList.js b/src/components/Posts/PostsList.js index f617b81..210c817 100644 --- a/src/components/Posts/PostsList.js +++ b/src/components/Posts/PostsList.js @@ -21,7 +21,6 @@ export const PostsList = ({ posts, getMore }) => ( ))} - {getMore &&