Skip to content
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
20 changes: 19 additions & 1 deletion src/AC/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
INCREMENT, DELETE_ARTICLE, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT, LOAD_ALL_ARTICLES, LOAD_ARTICLE,
START, SUCCESS, FAIL
START, SUCCESS, FAIL, LOAD_COMMENTS
} from '../constants'

export function increment() {
Expand Down Expand Up @@ -72,4 +72,22 @@ export function loadArticle(id) {

}, 1000)
}
}

export function loadComments(id) {
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)
}
}
16 changes: 6 additions & 10 deletions src/components/Comment.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {createCommentSelector} from '../selectors'
import {commentSelector} from '../selectors'
import { loadComments } from '../AC'

function Comment({comment}) {
return (
Expand All @@ -20,13 +21,8 @@ Comment.propTypes = {
}).isRequired
}

const createMapStateToProps = () => {
const commentSelector = createCommentSelector()
return (state, ownProps) => {
return {
comment: commentSelector(state, ownProps)
}
export default connect((state, ownProps) => {
return {
comment: commentSelector(state, ownProps)
}
}

export default connect(createMapStateToProps)(Comment)
})(Comment)
24 changes: 21 additions & 3 deletions src/components/CommentList.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import CommentForm from './CommentForm'
import Comment from './Comment'
import toggleOpen from '../decorators/toggleOpen'
import { loadComments } from '../AC'
import Loader from './common/Loader'
import { commentsLoadingSelector, commentListSelector, commentsLoadedIDSelector } from '../selectors'

class CommentList extends Component {
static propTypes = {
Expand All @@ -12,6 +16,11 @@ class CommentList extends Component {
toggleOpen: PropTypes.func
}

componentWillReceiveProps({ isOpen, article, loadComments }) {
console.log(this.props.loadedID)
if (!this.props.isOpen && isOpen && (this.props.loadedID != article.id)) loadComments(article.id)
}

render() {
const {isOpen, toggleOpen} = this.props
const text = isOpen ? 'hide comments' : 'show comments'
Expand All @@ -24,12 +33,15 @@ class CommentList extends Component {
}

getBody() {
const {article: { comments, id }, isOpen} = this.props
const { comments, article: { id }, isOpen, loading, loaded} = this.props

if (!isOpen) return null

if (loading) return <Loader />

const body = comments.length ? (
<ul>
{comments.map(id => <li key = {id}><Comment id = {id} /></li>)}
{comments.map(item => <li key = {item.id}><Comment id = {item.id} /></li>)}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не понял. Зачем ты достаешь id, чтоб потом сразу же по этому id искать этот же коммент в сторе?

</ul>
) : <h3>No comments yet</h3>

Expand All @@ -43,4 +55,10 @@ class CommentList extends Component {
}


export default toggleOpen(CommentList)
export default connect(state => {
return {
loading: commentsLoadingSelector(state),
loadedID: commentsLoadedIDSelector(state),
comments: commentListSelector(state)
}
}, {loadComments})(toggleOpen(CommentList))
4 changes: 3 additions & 1 deletion src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ export const ADD_COMMENT = 'ADD_COMMENT'

export const START = '_START'
export const SUCCESS = '_SUCCESS'
export const FAIL = '_FAIL'
export const FAIL = '_FAIL'

export const LOAD_COMMENTS = 'LOAD_COMMENTS'
36 changes: 29 additions & 7 deletions src/reducer/comments.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
import { ADD_COMMENT } from '../constants'
import {normalizedComments} from '../fixtures'
import { Record } from 'immutable'
import { ADD_COMMENT, LOAD_COMMENTS, START, SUCCESS } from '../constants'
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,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

здесь не достаточно повесить loading на весь comments, ведь ты для конкрентной статьи загружаешь

loaded: false,
error: null,
articleID: null,
})

export default (state = new ReducerRecord(), action) => {
const { type, payload, randomId } = action

switch (type) {
case ADD_COMMENT:
return state.set(randomId, {
...payload.comment,
id: randomId
})
return state.setIn(['entities', randomId], new commentRecord({ ...payload.comment, id: randomId}))

case LOAD_COMMENTS + START:
return state
.set('loading', true)
.set('articleID', payload.id)

case LOAD_COMMENTS + SUCCESS:
return state
.set('entities', arrToMap(payload.response, commentRecord))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

сейчас загружая комменты для одной статьи ты перезатираешь прошлые; используй .mergeIn

.set('loading', false)
.set('loaded', true)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему loaded === true, ведь ты загрузил только для одной статьи?

}

return state
Expand Down
10 changes: 7 additions & 3 deletions src/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +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 commentListMapSelector = state => state.comments.entities
export const commentsLoadingSelector = state => state.comments.loading
export const commentsLoadedIDSelector = state => state.comments.articleID
export const idSelector = (_, props) => props.id

export const articlesSelector = createSelector(articlesMapSelector, articles => articles.valueSeq().toArray())
Expand All @@ -18,6 +20,8 @@ export const filtratedArticlesSelector = createSelector(articlesSelector, filter
})
})

export const createCommentSelector = () => createSelector(commentListSelector, idSelector, (comments, id) => {
return comments.get(id)
export const commentListSelector = createSelector(commentListMapSelector, comments => comments.valueSeq().toArray())

export const commentSelector = createSelector(commentListSelector, idSelector, (comments, id) => {
return comments.find(item => item.id == id)
})