diff --git a/dist/bundle.es.js b/dist/bundle.es.js
index b477130..6ed46ed 100644
--- a/dist/bundle.es.js
+++ b/dist/bundle.es.js
@@ -7,6 +7,7 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau
 require('proxy-polyfill');
 var uuid = require('uuid');
 var reselect = require('reselect');
+var reReselect = require('re-reselect');
 var fromEntries = _interopDefault(require('@ungap/from-entries'));
 
 const MINIMUM_PUBLISH_BID = 0.00000001;
@@ -2405,15 +2406,14 @@ var _extends$3 = Object.assign || function (target) { for (var i = 1; i < argume
 
 const selectState$1 = state => state.claims || {};
 
-const selectById = reselect.createSelector(selectState$1, state => state.byId || {});
-
-const selectPendingClaimsById = reselect.createSelector(selectState$1, state => state.pendingById || {});
+const selectById = state => selectState$1(state).byId || {};
+const selectPendingClaimsById = state => selectState$1(state).pendingById || {};
 
 const selectClaimsById = reselect.createSelector(selectById, selectPendingClaimsById, (byId, pendingById) => {
   return Object.assign(byId, pendingById); // do I need merged to keep metadata?
 });
 
-const selectClaimIdsByUri = reselect.createSelector(selectState$1, state => state.claimsByUri || {});
+const selectClaimIdsByUri = state => selectState$1(state).claimsByUri || {};
 
 const selectCurrentChannelPage = reselect.createSelector(selectState$1, state => state.currentChannelPage || 1);
 
@@ -2469,6 +2469,45 @@ const selectReflectingById = reselect.createSelector(selectState$1, state => sta
 
 const makeSelectClaimForClaimId = claimId => reselect.createSelector(selectClaimsById, byId => byId[claimId]);
 
+// Compare with makeSelectClaimForUri just down below
+const selectClaimForUri = reReselect.createCachedSelector(selectClaimIdsByUri, selectClaimsById, (state, uri) => uri, (state, uri, returnRepost = true) => returnRepost, (byUri, byId, uri, returnRepost) => {
+  console.log('  selectClaimForUri');
+
+  let validUri;
+  let channelClaimId;
+  let streamClaimId;
+  let isChannel;
+  try {
+    ({ isChannel, channelClaimId, streamClaimId } = parseURI(uri));
+    validUri = true;
+  } catch (e) {}
+
+  if (validUri && byUri) {
+    const claimId = uri && byUri[normalizeURI(uri)];
+    const claim = byId[claimId];
+
+    // Make sure to return the claim as is so apps can check if it's been resolved before (null) or still needs to be resolved (undefined)
+    if (claimId === null) {
+      return null;
+    } else if (claimId === undefined) {
+      return undefined;
+    }
+
+    const repostedClaim = claim && claim.reposted_claim;
+    if (repostedClaim && returnRepost) {
+      const channelUrl = claim.signing_channel && (claim.signing_channel.canonical_url || claim.signing_channel.permanent_url);
+
+      return _extends$3({}, repostedClaim, {
+        repost_url: normalizeURI(uri),
+        repost_channel_url: channelUrl,
+        repost_bid_amount: claim && claim.meta && claim.meta.effective_amount
+      });
+    } else {
+      return claim;
+    }
+  }
+})((state, uri, returnRepost = true) => `${uri}:${returnRepost ? '1' : '0'}`);
+
 const makeSelectClaimForUri = (uri, returnRepost = true) => reselect.createSelector(selectClaimIdsByUri, selectClaimsById, (byUri, byId) => {
   let validUri;
   let channelClaimId;
@@ -2605,6 +2644,11 @@ const makeSelectTotalPagesInChannelSearch = uri => reselect.createSelector(selec
   return byChannel['pageCount'];
 });
 
+const selectMetadataForUri = reReselect.createCachedSelector(selectClaimForUri, (claim, uri) => {
+  const metadata = claim && claim.value;
+  return metadata || (claim === undefined ? undefined : null);
+})((state, uri) => uri);
+
 const makeSelectMetadataForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => {
   const metadata = claim && claim.value;
   return metadata || (claim === undefined ? undefined : null);
@@ -2616,6 +2660,18 @@ const makeSelectMetadataItemForUri = (uri, key) => reselect.createSelector(makeS
 
 const makeSelectTitleForUri = uri => reselect.createSelector(makeSelectMetadataForUri(uri), metadata => metadata && metadata.title);
 
+// Compare with makeSelectDateForUri just down below
+const selectDateForUri = reReselect.createCachedSelector(selectClaimForUri, // (state, uri, ?returnRepost)
+claim => {
+  console.log('  selectDateForUri');
+  const timestamp = claim && claim.value && (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta && claim.meta.creation_timestamp ? claim.meta.creation_timestamp * 1000 : null);
+  if (!timestamp) {
+    return undefined;
+  }
+  const dateObj = new Date(timestamp);
+  return dateObj;
+})((state, uri) => uri);
+
 const makeSelectDateForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => {
   const timestamp = claim && claim.value && (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta && claim.meta.creation_timestamp ? claim.meta.creation_timestamp * 1000 : null);
   if (!timestamp) {
@@ -2809,6 +2865,10 @@ const makeSelectMyChannelPermUrlForName = name => reselect.createSelector(select
   return matchingClaim ? matchingClaim.permanent_url : null;
 });
 
+const selectTagsForUri = reReselect.createCachedSelector(selectMetadataForUri, metadata => {
+  return metadata && metadata.tags || [];
+})((state, uri) => uri);
+
 const makeSelectTagsForUri = uri => reselect.createSelector(makeSelectMetadataForUri(uri), metadata => {
   return metadata && metadata.tags || [];
 });
@@ -8147,6 +8207,7 @@ exports.selectBlocks = selectBlocks;
 exports.selectBuiltinCollections = selectBuiltinCollections;
 exports.selectChannelClaimCounts = selectChannelClaimCounts;
 exports.selectChannelImportPending = selectChannelImportPending;
+exports.selectClaimForUri = selectClaimForUri;
 exports.selectClaimIdsByUri = selectClaimIdsByUri;
 exports.selectClaimSearchByQuery = selectClaimSearchByQuery;
 exports.selectClaimSearchByQueryLastPageReached = selectClaimSearchByQueryLastPageReached;
@@ -8158,6 +8219,7 @@ exports.selectCreateCollectionError = selectCreateCollectionError;
 exports.selectCreatingChannel = selectCreatingChannel;
 exports.selectCreatingCollection = selectCreatingCollection;
 exports.selectCurrentChannelPage = selectCurrentChannelPage;
+exports.selectDateForUri = selectDateForUri;
 exports.selectDownloadUrlsCount = selectDownloadUrlsCount;
 exports.selectDownloadedUris = selectDownloadedUris;
 exports.selectDownloadingByOutpoint = selectDownloadingByOutpoint;
@@ -8195,6 +8257,7 @@ exports.selectIsResolvingPublishUris = selectIsResolvingPublishUris;
 exports.selectIsSendingSupport = selectIsSendingSupport;
 exports.selectIsStillEditing = selectIsStillEditing;
 exports.selectIsWalletReconnecting = selectIsWalletReconnecting;
+exports.selectMetadataForUri = selectMetadataForUri;
 exports.selectMyActiveClaims = selectMyActiveClaims;
 exports.selectMyChannelClaims = selectMyChannelClaims;
 exports.selectMyChannelUrls = selectMyChannelUrls;
@@ -8236,6 +8299,7 @@ exports.selectResolvingUris = selectResolvingUris;
 exports.selectSavedCollectionIds = selectSavedCollectionIds;
 exports.selectSupportsBalance = selectSupportsBalance;
 exports.selectSupportsByOutpoint = selectSupportsByOutpoint;
+exports.selectTagsForUri = selectTagsForUri;
 exports.selectTakeOverAmount = selectTakeOverAmount;
 exports.selectTipsBalance = selectTipsBalance;
 exports.selectToast = selectToast;
diff --git a/dist/flow-typed/rereselect.js b/dist/flow-typed/rereselect.js
new file mode 100644
index 0000000..31b8179
--- /dev/null
+++ b/dist/flow-typed/rereselect.js
@@ -0,0 +1,6 @@
+// @flow
+// We should be using the `reselect` that comes with flow-typed but it's going to take a ton of work to get that working
+// without any errors. For now it's any type
+declare module 're-reselect' {
+  declare module.exports: any;
+}
diff --git a/flow-typed/rereselect.js b/flow-typed/rereselect.js
new file mode 100644
index 0000000..31b8179
--- /dev/null
+++ b/flow-typed/rereselect.js
@@ -0,0 +1,6 @@
+// @flow
+// We should be using the `reselect` that comes with flow-typed but it's going to take a ton of work to get that working
+// without any errors. For now it's any type
+declare module 're-reselect' {
+  declare module.exports: any;
+}
diff --git a/package.json b/package.json
index dc6bc25..a74596a 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
   "dependencies": {
     "@ungap/from-entries": "^0.2.1",
     "proxy-polyfill": "0.1.6",
+    "re-reselect": "^4.0.0",
     "reselect": "^3.0.0",
     "uuid": "^8.3.1"
   },
diff --git a/src/index.js b/src/index.js
index 079665f..d812678 100644
--- a/src/index.js
+++ b/src/index.js
@@ -189,20 +189,24 @@ export {
 } from 'redux/selectors/collections';
 
 export {
+  selectClaimForUri,
   makeSelectClaimForUri,
   makeSelectClaimIsMine,
   makeSelectFetchingChannelClaims,
   makeSelectClaimsInChannelForPage,
   makeSelectTotalPagesInChannelSearch,
   makeSelectTotalClaimsInChannelSearch,
+  selectMetadataForUri,
   makeSelectMetadataForUri,
   makeSelectMetadataItemForUri,
   makeSelectThumbnailForUri,
   makeSelectCoverForUri,
   makeSelectTitleForUri,
+  selectDateForUri,
   makeSelectDateForUri,
   makeSelectAmountForUri,
   makeSelectEffectiveAmountForUri,
+  selectTagsForUri,
   makeSelectTagsForUri,
   makeSelectTagInClaimOrChannelForUri,
   makeSelectTotalStakedAmountForChannelUri,
diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js
index f5a03ed..f439663 100644
--- a/src/redux/selectors/claims.js
+++ b/src/redux/selectors/claims.js
@@ -2,20 +2,16 @@
 import { normalizeURI, parseURI } from 'lbryURI';
 import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
 import { createSelector } from 'reselect';
+import { createCachedSelector } from 're-reselect';
 import { isClaimNsfw, filterClaims } from 'util/claim';
 import * as CLAIM from 'constants/claim';
 
+type State = { claims: any };
+
 const selectState = state => state.claims || {};
 
-export const selectById = createSelector(
-  selectState,
-  state => state.byId || {}
-);
-
-export const selectPendingClaimsById = createSelector(
-  selectState,
-  state => state.pendingById || {}
-);
+export const selectById = (state: State) => selectState(state).byId || {};
+export const selectPendingClaimsById = (state: State) => selectState(state).pendingById || {};
 
 export const selectClaimsById = createSelector(
   selectById,
@@ -25,10 +21,7 @@ export const selectClaimsById = createSelector(
   }
 );
 
-export const selectClaimIdsByUri = createSelector(
-  selectState,
-  state => state.claimsByUri || {}
-);
+export const selectClaimIdsByUri = (state: State) => selectState(state).claimsByUri || {};
 
 export const selectCurrentChannelPage = createSelector(
   selectState,
@@ -132,6 +125,54 @@ export const makeSelectClaimForClaimId = (claimId: string) =>
     byId => byId[claimId]
   );
 
+// Compare with makeSelectClaimForUri just down below
+export const selectClaimForUri = createCachedSelector(
+  selectClaimIdsByUri,
+  selectClaimsById,
+  (state, uri) => uri,
+  (state, uri, returnRepost = true) => returnRepost,
+  (byUri, byId, uri, returnRepost) => {
+    console.log('  selectClaimForUri');
+
+    let validUri;
+    let channelClaimId;
+    let streamClaimId;
+    let isChannel;
+    try {
+      ({ isChannel, channelClaimId, streamClaimId } = parseURI(uri));
+      validUri = true;
+    } catch (e) {}
+
+    if (validUri && byUri) {
+      const claimId = uri && byUri[normalizeURI(uri)];
+      const claim = byId[claimId];
+
+      // Make sure to return the claim as is so apps can check if it's been resolved before (null) or still needs to be resolved (undefined)
+      if (claimId === null) {
+        return null;
+      } else if (claimId === undefined) {
+        return undefined;
+      }
+
+      const repostedClaim = claim && claim.reposted_claim;
+      if (repostedClaim && returnRepost) {
+        const channelUrl =
+          claim.signing_channel &&
+          (claim.signing_channel.canonical_url || claim.signing_channel.permanent_url);
+
+        return {
+          ...repostedClaim,
+          repost_url: normalizeURI(uri),
+          repost_channel_url: channelUrl,
+          repost_bid_amount: claim && claim.meta && claim.meta.effective_amount,
+        };
+      } else {
+        return claim;
+      }
+    }
+  }
+)((state, uri, returnRepost = true) => `${uri}:${returnRepost ? '1' : '0'}`);
+
 export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true) =>
   createSelector(
     selectClaimIdsByUri,
@@ -299,8 +340,8 @@ export const makeSelectMyPurchasesForPage = (query: ?string, page: number = 1) =
       const end = Number(page) * Number(CLAIM.PAGE_SIZE);
       return matchingFileInfos && matchingFileInfos.length
         ? matchingFileInfos
-          .slice(start, end)
-          .map(fileInfo => fileInfo.canonical_url || fileInfo.permanent_url)
+            .slice(start, end)
+            .map(fileInfo => fileInfo.canonical_url || fileInfo.permanent_url)
         : [];
     }
   );
@@ -360,6 +401,11 @@ export const makeSelectTotalPagesInChannelSearch = (uri: string) =>
     }
   );
 
+export const selectMetadataForUri = createCachedSelector(selectClaimForUri, (claim, uri) => {
+  const metadata = claim && claim.value;
+  return metadata || (claim === undefined ? undefined : null);
+})((state, uri) => uri);
+
 export const makeSelectMetadataForUri = (uri: string) =>
   createSelector(
     makeSelectClaimForUri(uri),
@@ -383,6 +429,27 @@ export const makeSelectTitleForUri = (uri: string) =>
     metadata => metadata && metadata.title
   );
 
+// Compare with makeSelectDateForUri just down below
+export const selectDateForUri = createCachedSelector(
+  selectClaimForUri, // (state, uri, ?returnRepost)
+  claim => {
+    console.log('  selectDateForUri');
+    const timestamp =
+      claim &&
+      claim.value &&
+      (claim.value.release_time
+        ? claim.value.release_time * 1000
+        : claim.meta && claim.meta.creation_timestamp
+        ? claim.meta.creation_timestamp * 1000
+        : null);
+    if (!timestamp) {
+      return undefined;
+    }
+    const dateObj = new Date(timestamp);
+    return dateObj;
+  }
+)((state, uri) => uri);
+
 export const makeSelectDateForUri = (uri: string) =>
   createSelector(
     makeSelectClaimForUri(uri),
@@ -393,8 +460,8 @@ export const makeSelectDateForUri = (uri: string) =>
         (claim.value.release_time
           ? claim.value.release_time * 1000
           : claim.meta && claim.meta.creation_timestamp
-            ? claim.meta.creation_timestamp * 1000
-            : null);
+          ? claim.meta.creation_timestamp * 1000
+          : null);
       if (!timestamp) {
         return undefined;
       }
@@ -723,6 +790,13 @@ export const makeSelectMyChannelPermUrlForName = (name: string) =>
     }
   );
 
+export const selectTagsForUri = createCachedSelector(
+  selectMetadataForUri,
+  (metadata: ?GenericMetadata) => {
+    return (metadata && metadata.tags) || [];
+  }
+)((state, uri) => uri);
+
 export const makeSelectTagsForUri = (uri: string) =>
   createSelector(
     makeSelectMetadataForUri(uri),
diff --git a/yarn.lock b/yarn.lock
index af93714..018e6a6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6755,6 +6755,11 @@ randomatic@^3.0.0:
     kind-of "^6.0.0"
     math-random "^1.0.1"
 
+re-reselect@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/re-reselect/-/re-reselect-4.0.0.tgz#9ddec4c72c4d952f68caa5aa4b76a9ed38b75cac"
+  integrity sha512-wuygyq8TXUlSdVXv2kigXxQNOgdb9m7LbIjwfTNGSpaY1riLd5e+VeQjlQMyUtrk0oiyhi1AqIVynworl3qxHA==
+
 react-is@^16.12.0:
   version "16.13.1"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"