Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the sixth lesson #48

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/ac/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
LOAD_ALL_ARTICLES,
LOAD_ARTICLE,
LOAD_ARTICLE_COMMENTS,
LOAD_ALL_COMMENTS,
SUCCESS,
FAIL,
START
Expand Down Expand Up @@ -87,3 +88,28 @@ export function loadArticleComments(articleId) {
callAPI: `/api/comment?article=${articleId}`
}
}

export function loadComments({ limit = 5, currentPage = 0 }) {
const offset = currentPage * 5
return (dispatch) => {
dispatch({
type: LOAD_ALL_COMMENTS + START
})

fetch(`/api/comment?limit=${limit}&offset=${offset}`)
.then((res) => res.json())
.then(({ total, records }) =>
dispatch({
type: LOAD_ALL_COMMENTS + SUCCESS,
payload: { pagesCount: parseInt(total / limit) },
response: records
})
)
.catch((error) =>
dispatch({
type: LOAD_ALL_COMMENTS + FAIL,
error
})
)
}
}
2 changes: 2 additions & 0 deletions src/components/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ArticlesPage from './routes/articles-page'
import UserForm from './user-form'
import Filters from './filters'
import Counter from './counter'
import CommentsPage from './routes/comments-page'

class App extends Component {
render() {
Expand Down Expand Up @@ -36,6 +37,7 @@ class App extends Component {
render={() => <h1>New Article Page</h1>}
/>
<Route path="/articles" component={ArticlesPage} />
<Route path="/comments" component={CommentsPage} />
<Route path="*" render={() => <h1>Not Found Page</h1>} />
</Switch>
</div>
Expand Down
74 changes: 74 additions & 0 deletions src/components/comment-list/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { Component, Fragment } from 'react'
import { connect } from 'react-redux'
import { NavLink } from 'react-router-dom'

import {
commentsListSelector,
commentsLoadingSelector,
commentsPagesCountSelector
} from '../../selectors'

import { loadComments } from '../../ac'

class PaginationComments extends Component {
constructor(props) {
super(props)
const { page } = this.props
this.state = {
currentPage: parseInt(page)
}
}

componentDidMount(oldProps) {
const { loadComments } = this.props
const { currentPage } = this.state
loadComments({ currentPage })
}

render() {
const { comments = [], loading, pagesCount } = this.props
const { currentPage } = this.state

// Эту проверку лучше делать на уровне CommentsPage?
if (currentPage > pagesCount) {
return <div>{'No comments'}</div>
}

return (
<div>
<ul>
{!loading
? comments.map((el) => (
<li key={el.id}>{`${el.id}: ${el.text}`}</li>
))
: `Loading...`}
</ul>
<NavLink
to={`/comments/${currentPage > 1 ? currentPage - 1 : 1}`}
activeStyle={{ color: 'red' }}
>
Previous
</NavLink>
<NavLink
to={`/comments/${
currentPage <= pagesCount ? currentPage + 1 : pagesCount
}`}
activeStyle={{ color: 'red' }}
>
Next
</NavLink>
</div>
)
}
}

export default connect(
(state) => {
return {
comments: commentsListSelector(state),
loading: commentsLoadingSelector(state),
pagesCount: commentsPagesCountSelector(state)
}
},
{ loadComments }
)(PaginationComments)
28 changes: 28 additions & 0 deletions src/components/routes/comments-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { Component, Fragment } from 'react'
import { Route } from 'react-router-dom'
import PaginationComments from '../comment-list/comments'

class CommentsPage extends Component {
static propTypes = {}

render() {
console.log('---', 'comments-page match: ', this.props.match)
// const title = this.props.match.isExact && <h1>Select an Article</h1>
return (
<Fragment>
<Route path="/comments/:page" children={this.getComments} />
</Fragment>
)
}

getComments = ({ match }) => {
console.log('---', 'comments match: ', match)

if (!match) return <h1>Please Select A Page</h1>

const { page } = match.params
return <PaginationComments page={page} key={page} />
}
}

export default CommentsPage
2 changes: 2 additions & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE'
export const ADD_COMMENT = 'ADD_COMMENT'
export const LOAD_ARTICLE_COMMENTS = 'LOAD_ARTICLE_COMMENTS'

export const LOAD_ALL_COMMENTS = 'LOAD_ALL_COMMENTS'

export const START = '_START'
export const SUCCESS = '_SUCCESS'
export const FAIL = '_FAIL'
28 changes: 26 additions & 2 deletions src/reducer/comments.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { ADD_COMMENT, LOAD_ARTICLE_COMMENTS, SUCCESS } from '../constants'
import {
ADD_COMMENT,
LOAD_ARTICLE_COMMENTS,
LOAD_ALL_COMMENTS,
START,
SUCCESS
} from '../constants'
import { Record, OrderedMap } from 'immutable'
import { arrToMap } from './utils'

Expand All @@ -8,8 +14,13 @@ const CommentRecord = Record({
user: null
})

// Реализованная пагинация ломает работу комментариев в связке со статьей
const ReducerRecord = Record({
entities: new OrderedMap({})
entities: new OrderedMap({}),
pagesCount: null,
loading: false,
loaded: false,
error: null
})

export default (state = new ReducerRecord(), action) => {
Expand All @@ -28,6 +39,19 @@ export default (state = new ReducerRecord(), action) => {
case LOAD_ARTICLE_COMMENTS + SUCCESS:
return state.mergeIn(['entities'], arrToMap(response, CommentRecord))

case LOAD_ALL_COMMENTS + START:
return state.set('loading', true).set('loaded', false)

case LOAD_ALL_COMMENTS + SUCCESS:
return (
state
// Не сохраняем в store предыдущий набор статей
.set(['entities'], arrToMap(response, CommentRecord))
.set('pagesCount', payload.pagesCount)
.set('loading', false)
.set('loaded', true)
)

default:
return state
}
Expand Down
14 changes: 12 additions & 2 deletions src/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@ export const articleListSelector = createSelector(
articlesMapSelector,
(articlesMap) => articlesMap.valueSeq().toArray()
)
export const commentsSelector = (state) => state.comments

export const commentsMapSelector = (state) => state.comments.entities
export const idSelector = (_, props) => props.id

export const commentsListSelector = createSelector(
commentsMapSelector,
(commentsMap) => commentsMap.valueSeq().toArray()
)

export const commentsPagesCountSelector = (state) => state.comments.pagesCount

export const commentsLoadingSelector = (state) => state.comments.loading

export const filtratedArticlesSelector = createSelector(
selectionSelector,
dateRangeSelector,
Expand All @@ -32,7 +42,7 @@ export const filtratedArticlesSelector = createSelector(
)

export const createCommentSelector = () =>
createSelector(commentsSelector, idSelector, (comments, id) => {
createSelector(commentsListSelector, idSelector, (comments, id) => {
return comments.getIn(['entities', id])
})

Expand Down