From 291969003d4bdcd417082fc4bd5e73810fcb3ad7 Mon Sep 17 00:00:00 2001 From: Denis1990 Date: Wed, 7 Feb 2018 21:44:11 +0300 Subject: [PATCH 1/2] Add loadComments --- src/AC/index.js | 24 ++++++++++++++++++++++-- src/components/CommentList.js | 18 +++++++++++++++--- src/constants/index.js | 1 + src/reducer/comments.js | 31 +++++++++++++++++++++++++++---- src/selectors/index.js | 12 ++++++++---- 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/src/AC/index.js b/src/AC/index.js index e3a996a..492e750 100644 --- a/src/AC/index.js +++ b/src/AC/index.js @@ -1,6 +1,6 @@ import { INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, - START, SUCCESS, FAIL + LOAD_COMMENTS, START, SUCCESS, FAIL } from '../constants' export function increment() { @@ -72,4 +72,24 @@ export function loadArticle(id) { }, 1000) } -} \ No newline at end of file +} + +export function loadComments(id) { + console.log('loadComments') + return (dispatch) => { + dispatch({ + type: LOAD_COMMENTS + START, + payload: { id } + }) + + setTimeout(() => { + fetch(`/api/comment?article=${id}`) + .then(res => res.json()) + .then(response => dispatch({ + type: LOAD_COMMENTS + SUCCESS, + payload: { id, response } + })) + + }, 1000) + } +} diff --git a/src/components/CommentList.js b/src/components/CommentList.js index 3082942..9bde540 100644 --- a/src/components/CommentList.js +++ b/src/components/CommentList.js @@ -1,8 +1,12 @@ import React, {Component} from 'react' +import {connect} from 'react-redux' import PropTypes from 'prop-types' import CommentForm from './CommentForm' import Comment from './Comment' import toggleOpen from '../decorators/toggleOpen' +import {loadComments} from '../AC' +import {commentListLoadingSelector, commentListLoadedSelector} from '../selectors' +import Loader from './common/Loader' class CommentList extends Component { static propTypes = { @@ -12,6 +16,10 @@ class CommentList extends Component { toggleOpen: PropTypes.func } + componentWillReceiveProps({ isOpen, article, loadComments, loadded }) { + if (!this.props.isOpen && isOpen) loadComments(article.id) + } + render() { const {isOpen, toggleOpen} = this.props const text = isOpen ? 'hide comments' : 'show comments' @@ -24,12 +32,12 @@ class CommentList extends Component { } getBody() { - const {article: { comments, id }, isOpen} = this.props + const {article: { comments, id }, isOpen, loading, loadded} = this.props if (!isOpen) return null const body = comments.length ? ( ) :

No comments yet

@@ -43,4 +51,8 @@ class CommentList extends Component { } -export default toggleOpen(CommentList) \ No newline at end of file +export default connect(state => { + return { + + } +}, { loadComments })(toggleOpen(CommentList)) \ No newline at end of file diff --git a/src/constants/index.js b/src/constants/index.js index f34f842..8a18b45 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -8,6 +8,7 @@ export const CHANGE_SELECTION = 'CHANGE_SELECTION' export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE' export const ADD_COMMENT = 'ADD_COMMENT' +export const LOAD_COMMENTS = 'LOAD_COMMENTS' export const START = '_START' export const SUCCESS = '_SUCCESS' diff --git a/src/reducer/comments.js b/src/reducer/comments.js index 764e28c..d2ee22c 100644 --- a/src/reducer/comments.js +++ b/src/reducer/comments.js @@ -1,17 +1,40 @@ -import { ADD_COMMENT } from '../constants' +import { Map, Record } from 'immutable' +import { ADD_COMMENT, LOAD_COMMENTS, START, SUCCESS } from '../constants' import {normalizedComments} from '../fixtures' import {arrToMap} from './utils' -export default (state = arrToMap(normalizedComments), action) => { +const CommentRecord = Record({ + id: null, + user: null, + text: null +}) + +const ReducerRecord = Record({ + entities: arrToMap([], CommentRecord), + loading: false, + loaded: false, + error: null +}) + +export default (comments = new ReducerRecord(), action) => { const { type, payload, randomId } = action + console.log('payload--', payload) + switch (type) { case ADD_COMMENT: - return state.set(randomId, { + return comments.set(randomId, { ...payload.comment, id: randomId }) + + case LOAD_COMMENTS + START: + return comments.setIn(['entities', payload.id, 'loading'], true) + + case LOAD_COMMENTS + SUCCESS: + return comments + .setIn(['entities', payload.id], arrToMap(payload.response, CommentRecord)) } - return state + return comments } \ No newline at end of file diff --git a/src/selectors/index.js b/src/selectors/index.js index c358756..1c839a5 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -3,8 +3,9 @@ import {createSelector} from 'reselect' export const articlesMapSelector = state => state.articles.entities export const articlesLoadingSelector = state => state.articles.loading export const filtersSelector = state => state.filters -export const commentListSelector = state => state.comments +export const commentsSelector = state => state.comments.entities export const idSelector = (_, props) => props.id +export const articleIdSelector = (_, props) => props.articleId export const articlesSelector = createSelector(articlesMapSelector, articles => articles.valueSeq().toArray()) @@ -18,6 +19,9 @@ export const filtratedArticlesSelector = createSelector(articlesSelector, filter }) }) -export const createCommentSelector = () => createSelector(commentListSelector, idSelector, (comments, id) => { - return comments.get(id) -}) \ No newline at end of file +export const createCommentSelector = () => { + return createSelector(commentsSelector, idSelector, articleIdSelector, (comments, id, articleIdSelector) => { + console.log('comments--', comments) + return comments + }) +} \ No newline at end of file From 4ac33ffd17a7c32f353ba54c8fecad1cf6a2d1e7 Mon Sep 17 00:00:00 2001 From: Denis1990 Date: Wed, 7 Feb 2018 23:57:17 +0300 Subject: [PATCH 2/2] Fix errors --- src/AC/index.js | 1 - src/components/CommentList.js | 19 ++++++++----------- src/reducer/articles.js | 14 +++++++++++++- src/reducer/comments.js | 18 ++---------------- src/selectors/index.js | 9 ++++----- 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/AC/index.js b/src/AC/index.js index 492e750..d2f997b 100644 --- a/src/AC/index.js +++ b/src/AC/index.js @@ -75,7 +75,6 @@ export function loadArticle(id) { } export function loadComments(id) { - console.log('loadComments') return (dispatch) => { dispatch({ type: LOAD_COMMENTS + START, diff --git a/src/components/CommentList.js b/src/components/CommentList.js index 9bde540..d0d3b35 100644 --- a/src/components/CommentList.js +++ b/src/components/CommentList.js @@ -5,7 +5,6 @@ import CommentForm from './CommentForm' import Comment from './Comment' import toggleOpen from '../decorators/toggleOpen' import {loadComments} from '../AC' -import {commentListLoadingSelector, commentListLoadedSelector} from '../selectors' import Loader from './common/Loader' class CommentList extends Component { @@ -16,8 +15,9 @@ class CommentList extends Component { toggleOpen: PropTypes.func } - componentWillReceiveProps({ isOpen, article, loadComments, loadded }) { - if (!this.props.isOpen && isOpen) loadComments(article.id) + componentWillReceiveProps({ isOpen, article, loadComments }) { + console.log('article--', article) + if (!this.props.isOpen && isOpen && !article.loadedComments) loadComments(article.id) } render() { @@ -32,12 +32,13 @@ class CommentList extends Component { } getBody() { - const {article: { comments, id }, isOpen, loading, loadded} = this.props + const {article: { comments, id, loadedComments, loadingComments }, isOpen} = this.props if (!isOpen) return null + if (loadingComments) return - const body = comments.length ? ( + const body = comments.length && loadedComments ? (
    - {comments.map(id =>
  • )} + {comments.map(id =>
  • )}
) :

No comments yet

@@ -51,8 +52,4 @@ class CommentList extends Component { } -export default connect(state => { - return { - - } -}, { loadComments })(toggleOpen(CommentList)) \ No newline at end of file +export default connect(null, { loadComments })(toggleOpen(CommentList)) \ No newline at end of file diff --git a/src/reducer/articles.js b/src/reducer/articles.js index fd5939a..713b0ab 100644 --- a/src/reducer/articles.js +++ b/src/reducer/articles.js @@ -1,5 +1,5 @@ import { Map, Record } from 'immutable' -import { DELETE_ARTICLE, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, START, SUCCESS, FAIL } from '../constants' +import { DELETE_ARTICLE, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE, START, SUCCESS, FAIL, LOAD_COMMENTS } from '../constants' import {arrToMap} from './utils' const ArticleRecord = Record({ @@ -8,6 +8,8 @@ const ArticleRecord = Record({ text: null, date: null, loading: false, + loadedComments: false, + loadingComments: false, comments: [] }) @@ -50,6 +52,16 @@ export default (articles = new ReducerRecord(), action) => { case LOAD_ARTICLE + SUCCESS: return articles.setIn(['entities', payload.id], new ArticleRecord(payload.response)) + + case LOAD_COMMENTS + START: + return articles + .setIn(['entities', payload.id, 'loadingComments'], true) + .setIn(['entities', payload.id, 'loadedComments'], false) + + case LOAD_COMMENTS + SUCCESS: + return articles + .setIn(['entities', payload.id, 'loadingComments'], false) + .setIn(['entities', payload.id, 'loadedComments'], true) } return articles diff --git a/src/reducer/comments.js b/src/reducer/comments.js index d2ee22c..ee92e01 100644 --- a/src/reducer/comments.js +++ b/src/reducer/comments.js @@ -1,6 +1,5 @@ import { Map, Record } from 'immutable' import { ADD_COMMENT, LOAD_COMMENTS, START, SUCCESS } from '../constants' -import {normalizedComments} from '../fixtures' import {arrToMap} from './utils' const CommentRecord = Record({ @@ -9,31 +8,18 @@ const CommentRecord = Record({ text: null }) -const ReducerRecord = Record({ - entities: arrToMap([], CommentRecord), - loading: false, - loaded: false, - error: null -}) - -export default (comments = new ReducerRecord(), action) => { +export default (comments = arrToMap([], CommentRecord), action) => { const { type, payload, randomId } = action - console.log('payload--', payload) - switch (type) { case ADD_COMMENT: return comments.set(randomId, { ...payload.comment, id: randomId }) - - case LOAD_COMMENTS + START: - return comments.setIn(['entities', payload.id, 'loading'], true) case LOAD_COMMENTS + SUCCESS: - return comments - .setIn(['entities', payload.id], arrToMap(payload.response, CommentRecord)) + return comments.merge(arrToMap(payload.response, CommentRecord)) } return comments diff --git a/src/selectors/index.js b/src/selectors/index.js index 1c839a5..0da3ad8 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -3,9 +3,9 @@ import {createSelector} from 'reselect' export const articlesMapSelector = state => state.articles.entities export const articlesLoadingSelector = state => state.articles.loading export const filtersSelector = state => state.filters -export const commentsSelector = state => state.comments.entities +export const commentsSelector = state => state.comments +export const commentsLoadedSelector = state => state.articles[state.article.id].loadedComments export const idSelector = (_, props) => props.id -export const articleIdSelector = (_, props) => props.articleId export const articlesSelector = createSelector(articlesMapSelector, articles => articles.valueSeq().toArray()) @@ -20,8 +20,7 @@ export const filtratedArticlesSelector = createSelector(articlesSelector, filter }) export const createCommentSelector = () => { - return createSelector(commentsSelector, idSelector, articleIdSelector, (comments, id, articleIdSelector) => { - console.log('comments--', comments) - return comments + return createSelector(commentsSelector, idSelector, (comments, id) => { + return comments.get(id) }) } \ No newline at end of file