Batch-resolve channels on doCommentList fetch
This commit is contained in:
parent
7c304702d6
commit
96e7fda26a
7 changed files with 79 additions and 164 deletions
2
flow-typed/Comment.js
vendored
2
flow-typed/Comment.js
vendored
|
@ -148,7 +148,7 @@ declare type CommentListParams = {
|
|||
channel_name?: string, // signing channel name of claim (enables 'commentsEnabled' check)
|
||||
channel_id?: string, // signing channel claim id of claim (enables 'commentsEnabled' check)
|
||||
author_claim_id?: string, // filters comments to just this author
|
||||
parent_id?: string, // filters comments to those under this thread
|
||||
parent_id?: ?string, // filters comments to those under this thread
|
||||
top_level?: boolean, // filters to only top level comments
|
||||
hidden?: boolean, // if true, will show hidden comments as well
|
||||
sort_by?: number, // @see: ui/constants/comments.js::SORT_BY
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doResolveUris } from 'redux/actions/claims';
|
||||
import {
|
||||
selectClaimForUri,
|
||||
makeSelectClaimForUri,
|
||||
selectClaimIsMine,
|
||||
selectFetchingMyChannels,
|
||||
} from 'redux/selectors/claims';
|
||||
import { selectClaimForUri, selectClaimIsMine, selectFetchingMyChannels } from 'redux/selectors/claims';
|
||||
import {
|
||||
selectTopLevelCommentsForUri,
|
||||
makeSelectTopLevelTotalPagesForUri,
|
||||
|
@ -28,25 +22,16 @@ const select = (state, props) => {
|
|||
const { uri } = props;
|
||||
|
||||
const claim = selectClaimForUri(state, uri);
|
||||
const channelId = getChannelIdFromClaim(claim);
|
||||
|
||||
const activeChannelClaim = selectActiveChannelClaim(state);
|
||||
const topLevelComments = selectTopLevelCommentsForUri(state, uri);
|
||||
|
||||
const resolvedComments =
|
||||
topLevelComments && topLevelComments.length > 0
|
||||
? topLevelComments.filter(({ channel_url }) => makeSelectClaimForUri(channel_url)(state) !== undefined)
|
||||
: [];
|
||||
|
||||
return {
|
||||
topLevelComments,
|
||||
resolvedComments,
|
||||
topLevelComments: selectTopLevelCommentsForUri(state, uri),
|
||||
allCommentIds: selectCommentIdsForUri(state, uri),
|
||||
pinnedComments: selectPinnedCommentsForUri(state, uri),
|
||||
topLevelTotalPages: makeSelectTopLevelTotalPagesForUri(uri)(state),
|
||||
totalComments: makeSelectTotalCommentsCountForUri(uri)(state),
|
||||
claimId: claim && claim.claim_id,
|
||||
channelId,
|
||||
channelId: getChannelIdFromClaim(claim),
|
||||
claimIsMine: selectClaimIsMine(state, claim),
|
||||
isFetchingComments: selectIsFetchingComments(state),
|
||||
isFetchingCommentsById: selectIsFetchingCommentsById(state),
|
||||
|
@ -64,7 +49,6 @@ const perform = {
|
|||
fetchComment: doCommentById,
|
||||
fetchReacts: doCommentReactList,
|
||||
resetComments: doCommentReset,
|
||||
doResolveUris,
|
||||
};
|
||||
|
||||
export default connect(select, perform)(CommentsList);
|
||||
|
|
|
@ -30,7 +30,6 @@ type Props = {
|
|||
allCommentIds: any,
|
||||
pinnedComments: Array<Comment>,
|
||||
topLevelComments: Array<Comment>,
|
||||
resolvedComments: Array<Comment>,
|
||||
topLevelTotalPages: number,
|
||||
uri: string,
|
||||
claimId?: string,
|
||||
|
@ -47,11 +46,10 @@ type Props = {
|
|||
activeChannelId: ?string,
|
||||
settingsByChannelId: { [channelId: string]: PerChannelSettings },
|
||||
commentsAreExpanded?: boolean,
|
||||
fetchTopLevelComments: (uri: string, parentId: string, page: number, pageSize: number, sortBy: number) => void,
|
||||
fetchTopLevelComments: (uri: string, parentId: ?string, page: number, pageSize: number, sortBy: number) => void,
|
||||
fetchComment: (commentId: string) => void,
|
||||
fetchReacts: (commentIds: Array<string>) => Promise<any>,
|
||||
resetComments: (claimId: string) => void,
|
||||
doResolveUris: (uris: Array<string>, returnCachedClaims: boolean) => void,
|
||||
};
|
||||
|
||||
export default function CommentList(props: Props) {
|
||||
|
@ -60,7 +58,6 @@ export default function CommentList(props: Props) {
|
|||
uri,
|
||||
pinnedComments,
|
||||
topLevelComments,
|
||||
resolvedComments,
|
||||
topLevelTotalPages,
|
||||
claimId,
|
||||
channelId,
|
||||
|
@ -79,7 +76,6 @@ export default function CommentList(props: Props) {
|
|||
fetchComment,
|
||||
fetchReacts,
|
||||
resetComments,
|
||||
doResolveUris,
|
||||
} = props;
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
@ -89,7 +85,6 @@ export default function CommentList(props: Props) {
|
|||
const DEFAULT_SORT = ENABLE_COMMENT_REACTIONS ? SORT_BY.POPULARITY : SORT_BY.NEWEST;
|
||||
const [sort, setSort] = usePersistedState('comment-sort-by', DEFAULT_SORT);
|
||||
const [page, setPage] = React.useState(0);
|
||||
const [commentsToDisplay, setCommentsToDisplay] = React.useState(topLevelComments);
|
||||
const [didInitialPageFetch, setInitialPageFetch] = React.useState(false);
|
||||
const hasDefaultExpansion = commentsAreExpanded || !isMediumScreen || isMobile;
|
||||
const [expandedComments, setExpandedComments] = React.useState(hasDefaultExpansion);
|
||||
|
@ -97,9 +92,6 @@ export default function CommentList(props: Props) {
|
|||
const totalFetchedComments = allCommentIds ? allCommentIds.length : 0;
|
||||
const channelSettings = channelId ? settingsByChannelId[channelId] : undefined;
|
||||
const moreBelow = page < topLevelTotalPages;
|
||||
const isResolvingComments = topLevelComments && resolvedComments.length !== topLevelComments.length;
|
||||
const alreadyResolved = !isResolvingComments && resolvedComments.length !== 0;
|
||||
const canDisplayComments = commentsToDisplay && commentsToDisplay.length === topLevelComments.length;
|
||||
const title = getCommentsListTitle(totalComments);
|
||||
|
||||
// Display comments immediately if not fetching reactions
|
||||
|
@ -123,8 +115,7 @@ export default function CommentList(props: Props) {
|
|||
}
|
||||
setPage(1);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [page, uri, resetComments]); // 'claim' is derived from 'uri'
|
||||
}, [page, claimId, resetComments]);
|
||||
|
||||
// Fetch top-level comments
|
||||
useEffect(() => {
|
||||
|
@ -133,7 +124,7 @@ export default function CommentList(props: Props) {
|
|||
fetchComment(linkedCommentId);
|
||||
}
|
||||
|
||||
fetchTopLevelComments(uri, '', page, COMMENT_PAGE_SIZE_TOP_LEVEL, sort);
|
||||
fetchTopLevelComments(uri, undefined, page, COMMENT_PAGE_SIZE_TOP_LEVEL, sort);
|
||||
}
|
||||
}, [fetchComment, fetchTopLevelComments, linkedCommentId, page, sort, uri]);
|
||||
|
||||
|
@ -182,6 +173,8 @@ export default function CommentList(props: Props) {
|
|||
|
||||
// Infinite scroll
|
||||
useEffect(() => {
|
||||
if (topLevelComments.length === 0) return;
|
||||
|
||||
function shouldFetchNextPage(page, topLevelTotalPages, yPrefetchPx = 1000) {
|
||||
if (!spinnerRef || !spinnerRef.current) return false;
|
||||
|
||||
|
@ -216,7 +209,7 @@ export default function CommentList(props: Props) {
|
|||
setInitialPageFetch(true);
|
||||
}
|
||||
|
||||
if (hasDefaultExpansion && !isFetchingComments && canDisplayComments && readyToDisplayComments && moreBelow) {
|
||||
if (hasDefaultExpansion && !isFetchingComments && readyToDisplayComments && moreBelow) {
|
||||
const commentsInDrawer = Boolean(document.querySelector('.MuiDrawer-root .card--enable-overflow'));
|
||||
const scrollingElement = commentsInDrawer ? document.querySelector('.card--enable-overflow') : window;
|
||||
|
||||
|
@ -227,7 +220,7 @@ export default function CommentList(props: Props) {
|
|||
}
|
||||
}
|
||||
}, [
|
||||
canDisplayComments,
|
||||
topLevelComments,
|
||||
hasDefaultExpansion,
|
||||
didInitialPageFetch,
|
||||
isFetchingComments,
|
||||
|
@ -238,22 +231,6 @@ export default function CommentList(props: Props) {
|
|||
topLevelTotalPages,
|
||||
]);
|
||||
|
||||
// Wait to only display topLevelComments after resolved or else
|
||||
// other components will try to resolve again, like channelThumbnail
|
||||
useEffect(() => {
|
||||
if (!isResolvingComments) setCommentsToDisplay(topLevelComments);
|
||||
}, [isResolvingComments, topLevelComments]);
|
||||
|
||||
// Batch resolve comment channel urls
|
||||
useEffect(() => {
|
||||
if (!topLevelComments || alreadyResolved) return;
|
||||
|
||||
const urisToResolve = [];
|
||||
topLevelComments.map(({ channel_url }) => channel_url !== undefined && urisToResolve.push(channel_url));
|
||||
|
||||
if (urisToResolve.length > 0) doResolveUris(urisToResolve, true);
|
||||
}, [alreadyResolved, doResolveUris, topLevelComments]);
|
||||
|
||||
const commentProps = { isTopLevel: true, threadDepth: 3, uri, claimIsMine, linkedCommentId };
|
||||
const actionButtonsProps = { totalComments, sort, changeSort, setPage };
|
||||
|
||||
|
@ -282,7 +259,7 @@ export default function CommentList(props: Props) {
|
|||
<>
|
||||
{pinnedComments && <CommentElements comments={pinnedComments} {...commentProps} />}
|
||||
|
||||
{commentsToDisplay && <CommentElements comments={commentsToDisplay} {...commentProps} />}
|
||||
<CommentElements comments={topLevelComments} {...commentProps} />
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
|
@ -308,7 +285,7 @@ export default function CommentList(props: Props) {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{(isFetchingComments || (hasDefaultExpansion && moreBelow) || !canDisplayComments) && (
|
||||
{(isFetchingComments || (hasDefaultExpansion && moreBelow)) && (
|
||||
<div className="main--empty" ref={spinnerRef}>
|
||||
<Spinner type="small" />
|
||||
</div>
|
||||
|
|
|
@ -1,26 +1,16 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doResolveUris } from 'redux/actions/claims';
|
||||
import { selectClaimIsMineForUri, makeSelectClaimForUri } from 'redux/selectors/claims';
|
||||
import { selectClaimIsMineForUri } from 'redux/selectors/claims';
|
||||
import { selectIsFetchingCommentsByParentId, selectRepliesForParentId } from 'redux/selectors/comments';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import CommentsReplies from './view';
|
||||
|
||||
const select = (state, props) => {
|
||||
const fetchedReplies = selectRepliesForParentId(state, props.parentId);
|
||||
const resolvedReplies =
|
||||
fetchedReplies && fetchedReplies.length > 0
|
||||
? fetchedReplies.filter(({ channel_url }) => makeSelectClaimForUri(channel_url)(state) !== undefined)
|
||||
: [];
|
||||
const { uri, parentId } = props;
|
||||
|
||||
return {
|
||||
fetchedReplies,
|
||||
resolvedReplies,
|
||||
claimIsMine: selectClaimIsMineForUri(state, props.uri),
|
||||
userCanComment: IS_WEB ? Boolean(selectUserVerifiedEmail(state)) : true,
|
||||
isFetchingByParentId: selectIsFetchingCommentsByParentId(state),
|
||||
fetchedReplies: selectRepliesForParentId(state, parentId),
|
||||
claimIsMine: selectClaimIsMineForUri(state, uri),
|
||||
isFetching: selectIsFetchingCommentsByParentId(state, parentId),
|
||||
};
|
||||
};
|
||||
|
||||
const perform = (dispatch) => ({ doResolveUris: (uris) => dispatch(doResolveUris(uris, true)) });
|
||||
|
||||
export default connect(select, perform)(CommentsReplies);
|
||||
export default connect(select)(CommentsReplies);
|
||||
|
|
|
@ -6,61 +6,34 @@ import React from 'react';
|
|||
import Spinner from 'component/spinner';
|
||||
|
||||
type Props = {
|
||||
fetchedReplies: Array<Comment>,
|
||||
resolvedReplies: Array<Comment>,
|
||||
uri: string,
|
||||
parentId: string,
|
||||
claimIsMine: boolean,
|
||||
linkedCommentId?: string,
|
||||
userCanComment: boolean,
|
||||
threadDepth: number,
|
||||
numDirectReplies: number, // Total replies for parentId as reported by 'comment[replies]'. Includes blocked items.
|
||||
isFetchingByParentId: { [string]: boolean },
|
||||
hasMore: boolean,
|
||||
supportDisabled: boolean,
|
||||
doResolveUris: (Array<string>) => void,
|
||||
onShowMore?: () => void,
|
||||
// redux
|
||||
fetchedReplies: Array<Comment>,
|
||||
claimIsMine: boolean,
|
||||
isFetching: boolean,
|
||||
};
|
||||
|
||||
function CommentsReplies(props: Props) {
|
||||
export default function CommentsReplies(props: Props) {
|
||||
const {
|
||||
uri,
|
||||
parentId,
|
||||
fetchedReplies,
|
||||
resolvedReplies,
|
||||
claimIsMine,
|
||||
linkedCommentId,
|
||||
userCanComment,
|
||||
threadDepth,
|
||||
numDirectReplies,
|
||||
isFetchingByParentId,
|
||||
isFetching,
|
||||
hasMore,
|
||||
supportDisabled,
|
||||
doResolveUris,
|
||||
onShowMore,
|
||||
} = props;
|
||||
|
||||
const [isExpanded, setExpanded] = React.useState(true);
|
||||
const [commentsToDisplay, setCommentsToDisplay] = React.useState(fetchedReplies);
|
||||
const isResolvingReplies = fetchedReplies && resolvedReplies.length !== fetchedReplies.length;
|
||||
const alreadyResolved = !isResolvingReplies && resolvedReplies.length !== 0;
|
||||
const canDisplayComments = commentsToDisplay && commentsToDisplay.length === fetchedReplies.length;
|
||||
|
||||
// Batch resolve comment channel urls
|
||||
React.useEffect(() => {
|
||||
if (!fetchedReplies || alreadyResolved) return;
|
||||
|
||||
const urisToResolve = [];
|
||||
fetchedReplies.map(({ channel_url }) => channel_url !== undefined && urisToResolve.push(channel_url));
|
||||
|
||||
if (urisToResolve.length > 0) doResolveUris(urisToResolve);
|
||||
}, [alreadyResolved, doResolveUris, fetchedReplies]);
|
||||
|
||||
// Wait to only display topLevelComments after resolved or else
|
||||
// other components will try to resolve again, like channelThumbnail
|
||||
React.useEffect(() => {
|
||||
if (!isResolvingReplies) setCommentsToDisplay(fetchedReplies);
|
||||
}, [isResolvingReplies, fetchedReplies]);
|
||||
|
||||
return !numDirectReplies ? null : (
|
||||
<div className="comment__replies-container">
|
||||
|
@ -78,10 +51,7 @@ function CommentsReplies(props: Props) {
|
|||
<Button className="comment__threadline" aria-label="Hide Replies" onClick={() => setExpanded(false)} />
|
||||
|
||||
<ul className="comments--replies">
|
||||
{!isResolvingReplies &&
|
||||
commentsToDisplay &&
|
||||
commentsToDisplay.length > 0 &&
|
||||
commentsToDisplay.map((comment) => (
|
||||
{fetchedReplies.map((comment) => (
|
||||
<Comment
|
||||
key={comment.comment_id}
|
||||
threadDepth={threadDepth}
|
||||
|
@ -89,13 +59,13 @@ function CommentsReplies(props: Props) {
|
|||
comment={comment}
|
||||
claimIsMine={claimIsMine}
|
||||
linkedCommentId={linkedCommentId}
|
||||
commentingEnabled={userCanComment}
|
||||
supportDisabled={supportDisabled}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isExpanded && fetchedReplies && hasMore && (
|
||||
<div className="comment__actions--nested">
|
||||
<Button
|
||||
|
@ -106,7 +76,8 @@ function CommentsReplies(props: Props) {
|
|||
/>
|
||||
</div>
|
||||
)}
|
||||
{(isFetchingByParentId[parentId] || isResolvingReplies || !canDisplayComments) && (
|
||||
|
||||
{isFetching && (
|
||||
<div className="comment__replies-container">
|
||||
<div className="comment__actions--nested">
|
||||
<Spinner type="small" />
|
||||
|
@ -116,5 +87,3 @@ function CommentsReplies(props: Props) {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CommentsReplies;
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
import { makeSelectNotificationForCommentId } from 'redux/selectors/notifications';
|
||||
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
||||
import { toHex } from 'util/hex';
|
||||
import { getChannelFromClaim } from 'util/claim';
|
||||
import Comments from 'comments';
|
||||
import { selectPrefsReady } from 'redux/selectors/sync';
|
||||
import { doAlertWaitingForSync } from 'redux/actions/app';
|
||||
|
@ -30,47 +31,41 @@ const MENTION_REGEX = /(?:^| |\n)@[^\s=&#$@%?:;/"<>%{}|^~[]*(?::[\w]+)?/gm;
|
|||
|
||||
export function doCommentList(
|
||||
uri: string,
|
||||
parentId: string,
|
||||
parentId: ?string,
|
||||
page: number = 1,
|
||||
pageSize: number = 99999,
|
||||
sortBy: number = SORT_BY.NEWEST
|
||||
) {
|
||||
return (dispatch: Dispatch, getState: GetState) => {
|
||||
const state = getState();
|
||||
const claim = selectClaimsByUri(state)[uri];
|
||||
const claimId = claim ? claim.claim_id : null;
|
||||
const claim = selectClaimForUri(state, uri);
|
||||
const { claim_id: claimId } = claim || {};
|
||||
|
||||
if (!claimId) {
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_LIST_FAILED,
|
||||
data: 'unable to find claim for uri',
|
||||
});
|
||||
return;
|
||||
return dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: 'unable to find claim for uri' });
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_LIST_STARTED,
|
||||
data: {
|
||||
parentId,
|
||||
},
|
||||
});
|
||||
dispatch({ type: ACTIONS.COMMENT_LIST_STARTED, data: { parentId } });
|
||||
|
||||
// Adding 'channel_id' and 'channel_name' enables "CreatorSettings > commentsEnabled".
|
||||
const creatorChannelClaim = claim.value_type === 'channel' ? claim : claim.signing_channel;
|
||||
const creatorChannelClaim = getChannelFromClaim(claim);
|
||||
const { claim_id: creatorClaimId, name: channelName } = creatorChannelClaim || {};
|
||||
|
||||
return Comments.comment_list({
|
||||
page,
|
||||
claim_id: claimId,
|
||||
page_size: pageSize,
|
||||
parent_id: parentId || undefined,
|
||||
parent_id: parentId,
|
||||
top_level: !parentId,
|
||||
channel_id: creatorChannelClaim ? creatorChannelClaim.claim_id : undefined,
|
||||
channel_name: creatorChannelClaim ? creatorChannelClaim.name : undefined,
|
||||
channel_id: creatorClaimId,
|
||||
channel_name: channelName,
|
||||
sort_by: sortBy,
|
||||
})
|
||||
.then((result: CommentListResponse) => {
|
||||
const { items: comments, total_items, total_filtered_items, total_pages } = result;
|
||||
dispatch({
|
||||
|
||||
const commentChannelUrls = comments && comments.map((comment) => comment.channel_url || '');
|
||||
const dispatchData = {
|
||||
type: ACTIONS.COMMENT_LIST_COMPLETED,
|
||||
data: {
|
||||
comments,
|
||||
|
@ -78,38 +73,36 @@ export function doCommentList(
|
|||
totalItems: total_items,
|
||||
totalFilteredItems: total_filtered_items,
|
||||
totalPages: total_pages,
|
||||
claimId: claimId,
|
||||
creatorClaimId: creatorChannelClaim ? creatorChannelClaim.claim_id : undefined,
|
||||
uri: uri,
|
||||
claimId,
|
||||
creatorClaimId,
|
||||
uri,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Batch resolve comment channel urls
|
||||
if (commentChannelUrls) {
|
||||
return dispatch(async () => await doResolveUris(commentChannelUrls, true)).then(() => {
|
||||
dispatch({ ...dispatchData });
|
||||
|
||||
return result;
|
||||
});
|
||||
} else {
|
||||
dispatch({ ...dispatchData });
|
||||
|
||||
return result;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
switch (error.message) {
|
||||
const { message } = error;
|
||||
|
||||
switch (message) {
|
||||
case 'comments are disabled by the creator':
|
||||
dispatch({
|
||||
type: ACTIONS.COMMENT_LIST_COMPLETED,
|
||||
data: {
|
||||
creatorClaimId: creatorChannelClaim ? creatorChannelClaim.claim_id : undefined,
|
||||
disabled: true,
|
||||
},
|
||||
});
|
||||
break;
|
||||
|
||||
return dispatch({ type: ACTIONS.COMMENT_LIST_COMPLETED, data: { creatorClaimId, disabled: true } });
|
||||
case FETCH_API_FAILED_TO_FETCH:
|
||||
dispatch(
|
||||
doToast({
|
||||
isError: true,
|
||||
message: __('Failed to fetch comments.'),
|
||||
})
|
||||
);
|
||||
dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error });
|
||||
break;
|
||||
|
||||
dispatch(doToast({ isError: true, message: __('Failed to fetch comments.') }));
|
||||
return dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error });
|
||||
default:
|
||||
dispatch(doToast({ isError: true, message: `${error.message}` }));
|
||||
dispatch(doToast({ isError: true, message: `${message}` }));
|
||||
dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error });
|
||||
}
|
||||
});
|
||||
|
|
|
@ -24,7 +24,6 @@ export const selectCommentsById = (state: State) => selectState(state).commentBy
|
|||
export const selectCommentIdsByClaimId = (state: State) => selectState(state).byId;
|
||||
export const selectIsFetchingComments = (state: State) => selectState(state).isLoading;
|
||||
export const selectIsFetchingCommentsById = (state: State) => selectState(state).isLoadingById;
|
||||
export const selectIsFetchingCommentsByParentId = (state: State) => selectState(state).isLoadingByParentId;
|
||||
export const selectIsFetchingReacts = (state: State) => selectState(state).isFetchingReacts;
|
||||
|
||||
export const selectMyReacts = (state: State) => state.comments.myReactsByCommentId;
|
||||
|
@ -32,6 +31,9 @@ export const selectMyReactsForComment = (state: State, commentIdChannelId: strin
|
|||
// @commentIdChannelId: Format = 'commentId:MyChannelId'
|
||||
return state.comments.myReactsByCommentId && state.comments.myReactsByCommentId[commentIdChannelId];
|
||||
};
|
||||
export const selectIsFetchingCommentsByParentId = (state: State, parentId: string) => {
|
||||
return selectState(state).isLoadingByParentId[parentId];
|
||||
};
|
||||
|
||||
export const selectOthersReacts = (state: State) => state.comments.othersReactsByCommentId;
|
||||
export const selectOthersReactsForComment = (state: State, id: string) => {
|
||||
|
|
Loading…
Reference in a new issue