somn45 / mucketlist

React, Typescript, Spotify API를 이용해 좋아하는 장르의 곡을 지속적으로 추적, 몰랐던 명곡을 저장할 수 있는 APP
0 stars 0 forks source link

트랙들이 옵션에 맞게 정렬되지 않습니다. #6

Closed somn45 closed 2 years ago

somn45 commented 2 years ago

현재 mucketlist 앱은 트랙을 불러오고 나서 트랙의 정렬 여부를 결정하는 옵션(인기순, 발매순, 랜덤)이 존재합니다. 트랙을 기존 useState에서 사용할 때에는 이 옵션들이 적용이 되었습니다. 그런데 트랙을 Redux Toolkit에서 관리한 이후로 트랙의 정렬 옵션이 적용되지 않습니다. 현재 트랙을 정렬하는 메서드는 array.sort입니다.

// 트랙을 인기순대로 정렬하는 메서드
  sortByPopularity: (state, action) => {
    state.sort((a, b) => {
      if (a.popularity > b.popularity) return 1;
      else if (b.popularity > a.popularity) return -1;
      else return 0;
    });

reducer 전체 코드와 이와 관련된 코드를 아래에 올려놓겠습니다.

// tracksReducer.tsx
import { createSlice } from '@reduxjs/toolkit';
import { TrackState } from '../../pages/Settings';

const tracks = createSlice({
  name: 'tracksReducer',
  initialState: [] as TrackState[],
  reducers: {
    createTracks: (state, action) => {
      return [...action.payload];
    },
    sortByPopularity: (state, action) => {
      state.sort((a, b) => {
        if (a.popularity > b.popularity) return 1;
        else if (b.popularity > a.popularity) return -1;
        else return 0;
      });
    },
    sortByRelease: (state, action) => {
      state.sort((a, b) => {
        if (a.album.release_date > b.album.release_date) return 1;
        else if (b.album.release_date > a.album.release_date) return -1;
        else return 0;
      });
    },
    sortByRandom: (state, action) => {
      state.sort((a, b) => {
        const randomNumber1 = Math.random();
        const randomNumber2 = Math.random();
        if (randomNumber1 > randomNumber2) return 1;
        else if (randomNumber2 > randomNumber1) return -1;
        else return 0;
      });
    },
  },
});

export default tracks;
// Settings.tsx
import React, { useState } from 'react';
import { connect, useDispatch } from 'react-redux';
import {
  sortByPopularity,
  sortByRelease,
  sortByRandom,
  addSettings,
} from '../store/store';

function Settings({ tracks }: ITracks) {
    ...
  };
  const setTrackOption = (e: React.MouseEvent<HTMLInputElement>) => {
    e.preventDefault();
    if (tracks.length === 0 && !Array.isArray(tracks)) return;
    if (selectedSetting === 'popularity') {
      dispatch(sortByPopularity(''));
    } else if (selectedSetting === 'date') {
      dispatch(sortByRelease(''));
    } else if (selectedSetting === 'random') {
      dispatch(sortByRandom(''));
    }
    localStorage.setItem('tracks', JSON.stringify(tracks));
    dispatch(addSettings(selectedSetting));
  };
  return (
    <form>
    ...
    </form>
  );
}

const mapStateToProps = (state: ITracks) => {
  return { tracks: state.tracks };
};

export default connect(mapStateToProps)(Settings);
somn45 commented 2 years ago

트랙 state가 localstorage에 저장하고 난 다음 옵션이 적용되어서 생긴 원인이었습니다. useState, redux를 혼용해서 사용하니 코드의 진행이 엇나갔나 봅니다. 그래서 대신 redux-persist 모듈을 대신 사용하여 해결했습니다. redux-persist는 redux의 상태를 지속 가능하게 만드는 모듈입니다. 브라우저의 새로고침, 종료 후에도 상태가 초기화 되는 현상을 막아줍니다. redux-persist를 사용한 수정 코드를 올려놓겠습니다.

// store.tsx
import { configureStore } from '@reduxjs/toolkit';
import { persistStore } from 'redux-persist';
import rootReducer from './reducers/rootReducer';

const store = configureStore({
  reducer: rootReducer,
});

// store를 지속 가능한 버전으로 선언
export const persistor = persistStore(store);

export default store;
import { combineReducers } from '@reduxjs/toolkit';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import accessToken from '../reducers/accessTokenReducer';
import firebaseUidToken from '../reducers/firebaseUidToken';
import genre from '../reducers/genreReducer';
import tracks from '../reducers/tracksReducer';
import settings from '../reducers/settingsReducer';

const rootReducer = combineReducers({
  accessToken: accessToken.reducer,
  firebaseUidToken: firebaseUidToken.reducer,
  genre: genre.reducer,
  tracks: tracks.reducer,
  settings: settings.reducer,
});

// redux-persist 옵션
const persistConfig = {
  key: 'rootReducer',  // 어느 지점에서 부터 지속 가능하게 만들건지 설정
  storage: storage,    // storage 종류 설정(localstorage, sessionstorage)
  whitelist: ['tracks'], // 지속 가능하게 만들 데이터 설정
};

export const { addAccessToken, getAccessToken } = accessToken.actions;
export const { addFirebaseUidToken, getFirebaseUidToken } =
  firebaseUidToken.actions;
export const { addGenre, removeGenre } = genre.actions;
export const { createTracks, sortByPopularity, sortByRelease, sortByRandom } =
  tracks.actions;
export const { addSettings, clearSettings } = settings.actions;

// rootReducer에 redux-persist 옵션 추가
export default persistReducer(persistConfig, rootReducer);