fixed perf issue related to too many rerenders

rerenders were caused by strict equality check on object/array picks
switched artistInfo to new store
updated zustand and fixed deprecation warnings
This commit is contained in:
austinried
2022-03-19 09:52:01 +09:00
parent 47c65ea8cb
commit 13af6555d3
15 changed files with 108 additions and 142 deletions

View File

@@ -6,7 +6,7 @@ import Header from '@app/components/Header'
import HeaderBar from '@app/components/HeaderBar'
import ListItem from '@app/components/ListItem'
import { Album, Song } from '@app/models/music'
import { useStore } from '@app/state/store'
import { useStore, useStoreDeep } from '@app/state/store'
import { selectTrackPlayer } from '@app/state/trackplayer'
import colors from '@app/styles/colors'
import dimensions from '@app/styles/dimensions'
@@ -70,7 +70,7 @@ const TopSongs = React.memo<{
const ArtistAlbums = React.memo<{
id: string
}>(({ id }) => {
const albums = useStore(
const albums = useStoreDeep(
useCallback(
store => {
const ids = store.entities.artistAlbums[id]
@@ -114,8 +114,8 @@ const ArtistViewFallback = React.memo(() => (
))
const ArtistView = React.memo<{ id: string; title: string }>(({ id, title }) => {
const artist = useStore(useCallback(store => store.entities.artists[id], [id]))
const artistInfo = useStore(useCallback(store => store.entities.artistInfo[id], [id]))
const artist = useStoreDeep(useCallback(store => store.entities.artists[id], [id]))
const artistInfo = useStoreDeep(useCallback(store => store.entities.artistInfo[id], [id]))
const fetchArtist = useStore(store => store.fetchLibraryArtist)
const fetchArtistInfo = useStore(store => store.fetchLibraryArtistInfo)

View File

@@ -3,21 +3,20 @@ import CoverArt from '@app/components/CoverArt'
import GradientScrollView from '@app/components/GradientScrollView'
import Header from '@app/components/Header'
import NothingHere from '@app/components/NothingHere'
import { useFetchPaginatedList } from '@app/hooks/list'
import { useActiveServerRefresh } from '@app/hooks/server'
import { AlbumListItem } from '@app/models/music'
import { Album, mapById } from '@app/state/library'
import { selectMusic } from '@app/state/music'
import { mapById } from '@app/state/library'
import { selectSettings } from '@app/state/settings'
import { Store, useStore } from '@app/state/store'
import { useStore, useStoreDeep } from '@app/state/store'
import colors from '@app/styles/colors'
import font from '@app/styles/font'
import { GetAlbumList2Params, GetAlbumList2TypeBase, GetAlbumListType } from '@app/subsonic/params'
import { GetAlbumList2TypeBase, GetAlbumListType } from '@app/subsonic/params'
import { useNavigation } from '@react-navigation/native'
import equal from 'fast-deep-equal/es6/react'
import produce from 'immer'
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'
import React, { useCallback, useState } from 'react'
import { RefreshControl, ScrollView, StatusBar, StyleSheet, Text, View } from 'react-native'
import create from 'zustand'
import create, { StateSelector } from 'zustand'
const titles: { [key in GetAlbumListType]?: string } = {
recent: 'Recently Played',
@@ -55,8 +54,8 @@ const AlbumItem = React.memo<{
const Category = React.memo<{
type: string
}>(({ type }) => {
const list = useHomeStore(useCallback(store => store.lists[type] || [], [type]))
const albums = useStore(useCallback(store => mapById(store.entities.albums, list), [list]))
const list = useHomeStoreDeep(useCallback(store => store.lists[type] || [], [type]))
const albums = useStoreDeep(useCallback(store => mapById(store.entities.albums, list), [list]))
const Albums = () => (
<ScrollView
@@ -90,7 +89,7 @@ interface HomeState {
setList: (type: string, list: string[]) => void
}
const useHomeStore = create<HomeState>((set, get) => ({
const useHomeStore = create<HomeState>(set => ({
lists: {},
setList: (type, list) => {
@@ -102,6 +101,10 @@ const useHomeStore = create<HomeState>((set, get) => ({
},
}))
function useHomeStoreDeep<U>(stateSelector: StateSelector<HomeState, U>) {
return useHomeStore(stateSelector, equal)
}
const Home = () => {
const [refreshing, setRefreshing] = useState(false)
const types = useStore(selectSettings.homeLists)
@@ -113,9 +116,7 @@ const Home = () => {
await Promise.all(
types.map(async type => {
console.log('fetch', type)
const ids = await fetchAlbumList({ type: type as GetAlbumList2TypeBase, size: 20, offset: 0 })
console.log('set', type)
setList(type, ids)
}),
)

View File

@@ -6,13 +6,12 @@ import { useFetchPaginatedList } from '@app/hooks/list'
import { Album, AlbumListItem } from '@app/models/music'
import { mapById } from '@app/state/library'
import { selectSettings } from '@app/state/settings'
import { Store, useStore } from '@app/state/store'
import { useStore, useStoreDeep } from '@app/state/store'
import colors from '@app/styles/colors'
import font from '@app/styles/font'
import { GetAlbumList2Params, GetAlbumList2Type } from '@app/subsonic/params'
import { useNavigation } from '@react-navigation/native'
import pick from 'lodash.pick'
import React, { useCallback, useEffect } from 'react'
import React, { useCallback } from 'react'
import { StyleSheet, Text, useWindowDimensions, View } from 'react-native'
const AlbumItem = React.memo<{
@@ -97,7 +96,7 @@ const AlbumsList = () => {
)
const { list, refreshing, refresh, fetchNextPage } = useFetchPaginatedList(fetchPage, 300)
const albums = useStore(useCallback(store => mapById(store.entities.albums, list), [list]))
const albums = useStoreDeep(useCallback(store => mapById(store.entities.albums, list), [list]))
const layout = useWindowDimensions()

View File

@@ -5,7 +5,7 @@ import { useFetchList2 } from '@app/hooks/list'
import { Artist } from '@app/models/music'
import { ArtistFilterType } from '@app/models/settings'
import { selectSettings } from '@app/state/settings'
import { Store, useStore } from '@app/state/store'
import { useStore, useStoreDeep } from '@app/state/store'
import React, { useEffect, useState } from 'react'
import { StyleSheet, View } from 'react-native'
@@ -19,12 +19,10 @@ const filterOptions: OptionData[] = [
{ text: 'Random', value: 'random' },
]
const selectArtists = (store: Store) => store.entities.artists
const ArtistsList = () => {
const fetchArtists = useStore(store => store.fetchLibraryArtists)
const { refreshing, refresh } = useFetchList2(fetchArtists)
const artists = useStore(selectArtists)
const artists = useStoreDeep(store => store.entities.artists)
const filter = useStore(selectSettings.libraryArtistFilter)
const setFilter = useStore(selectSettings.setLibraryArtistFiler)

View File

@@ -1,10 +1,9 @@
import GradientFlatList from '@app/components/GradientFlatList'
import ListItem from '@app/components/ListItem'
import { useFetchList, useFetchList2 } from '@app/hooks/list'
import { useFetchList2 } from '@app/hooks/list'
import { PlaylistListItem } from '@app/models/music'
import { selectMusic } from '@app/state/music'
import { useStore } from '@app/state/store'
import React, { useCallback, useState } from 'react'
import { useStore, useStoreDeep } from '@app/state/store'
import React from 'react'
import { StyleSheet } from 'react-native'
const PlaylistRenderItem: React.FC<{ item: PlaylistListItem }> = ({ item }) => (
@@ -14,7 +13,7 @@ const PlaylistRenderItem: React.FC<{ item: PlaylistListItem }> = ({ item }) => (
const PlaylistsList = () => {
const fetchPlaylists = useStore(store => store.fetchLibraryPlaylists)
const { refreshing, refresh } = useFetchList2(fetchPlaylists)
const playlists = useStore(store => store.entities.playlists)
const playlists = useStoreDeep(store => store.entities.playlists)
return (
<GradientFlatList

View File

@@ -5,13 +5,12 @@ import ImageGradientFlatList from '@app/components/ImageGradientFlatList'
import ListItem from '@app/components/ListItem'
import ListPlayerControls from '@app/components/ListPlayerControls'
import { useCoverArtFile } from '@app/hooks/cache'
import { useAlbumWithSongs, usePlaylistWithSongs } from '@app/hooks/music'
import { Album, AlbumWithSongs, PlaylistListItem, PlaylistWithSongs, Song } from '@app/models/music'
import { useStore } from '@app/state/store'
import { usePlaylistWithSongs } from '@app/hooks/music'
import { Album, PlaylistListItem, Song } from '@app/models/music'
import { useStore, useStoreDeep } from '@app/state/store'
import { selectTrackPlayer } from '@app/state/trackplayer'
import colors from '@app/styles/colors'
import font from '@app/styles/font'
import pick from 'lodash.pick'
import React, { useCallback, useEffect, useState } from 'react'
import { ActivityIndicator, StyleSheet, Text, View } from 'react-native'
@@ -139,8 +138,8 @@ const AlbumView = React.memo<{
}>(({ id, title }) => {
// const album = useAlbumWithSongs(id)
const album = useStore(useCallback(store => store.entities.albums[id], [id]))
const songs = useStore(
const album = useStoreDeep(useCallback(store => store.entities.albums[id], [id]))
const songs = useStoreDeep(
useCallback(
store => {
const ids = store.entities.albumSongs[id]