Проблема с повторным выбором при добавлении нового элемента в большой массив - PullRequest
0 голосов
/ 30 октября 2018

Я использую Повторный выбор для создания различных селекторов для React + Redux. У меня возникают проблемы с производительностью, когда у меня более 1 млн элементов, вычисление селектора может занять от 300 мс до 500 мс, поскольку оно должно фильтровать и сортировать все элементы с дорогими проверками.

Я нормализую состояние в Redux, где у меня есть элементы, хранящиеся в byIds, и идентификаторы, хранящиеся в allIds. Это все хорошо. Но когда я добавляю новый элемент, byIds и allIds будут обновлены, а это означает, что селектору придется заново вычислять все элементы 1M, а не просто вычислять новый элемент.

Есть какой-нибудь умный способ решить это, или я что-то упускаю. Ранее я не использовал селекторы. Это означало, что я отфильтровал все новые элементы до того, как они были добавлены в хранилище, но это привело к тому, что мои данные не были чистыми.

Некоторые методы, о которых я думал, - это реструктуризация моих данных или создание каких-то слоев для данных, чтобы я мог лучше запомнить их часть.

Вот структура моих селекторов:

  1. getVisiblePostsIds - получает postsIds, который имеет идентификатор всех элементов и фильтрует их. Например. элемент, который заблокирован или имеет неправильный тип, должен быть отфильтрован.
  2. getSortedPostsIds - получает getVisiblePostsIds и сортирует элементы по условию
  3. getFilteredPostsIds - получает getSortedPostsIds и нарезает массив элементов, если их слишком много.

Вот примерный исходный код, если он может помочь.

const getVisiblePostsIds = createSelector(
    [
        getFeedsByIds,
        getPostsIds,
        getPostsByIds,
        getFeedType,
        getStartDate,
        getModerationDict,
    ],
    (
        feedsByIds,
        postsIds,
        postsByIds,
        feedType,
        startTime,
        moderationDict,
    ) => {
        return postsIds.filter(
            postId =>
                postsByIds[postId].created >= startTime
                && feedsByIds[postsByIds[postId].feedId].IgnoreStartDate === false
                && moderationDict[postsByIds[postId].mediaId] === undefined
                && moderationDict[postsByIds[postId].userId] === undefined
                && (feedType === FEED_TYPE.SHOW_BOTH
                    || (feedType === FEED_TYPE.SHOW_MEDIA_FEED_ONLY && postsByIds[postId].type > 1)
                    || (feedType === FEED_TYPE.SHOW_TEXT_FEED_ONLY && postsByIds[postId].type === POST_TYPE.TEXT)),
        )
    },
)

const getSortedPostsIds = createSelector(
    [
        getSlideArrangement,
        getVisiblePostsIds,
        getPostsByIds,
    ],
    (
        slideArrangement,
        postsIds,
        postsByIds,
        // .slice() is supposed to be faster than [...postIds] to clone the array without mutation
    ) => postsIds.slice().sort(comparePosts(postsByIds, slideArrangement)),
)

export const getFilteredPostsIds = createSelector(
    [
        getSortedPostsIds,
        getHasLoopLimit,
        getLoopLimit,
        getSlideArrangement,
    ],
    (
        postsIds,
        hasLoopLimit,
        loopLimit,
        slideArrangement,
    ) => {
        ...array slice
    },
)

Спасибо.

...