검색 기능 - 회원 검색(닉네임으로 검색), 피드 검색(해시태그로 검색, 날씨 및 장소 정보로 검색)
ㆍProject Diary/React + MariaDB (PicShare WebApp)
검색 기능은 사용자가 ID로 회원을 검색하거나, 해시태그, 날씨 및 장소 정보로 피드를 검색할 수 있도록 도와줍니다. 이를 위해 Redux 설정, 검색 컴포넌트 작성, 그리고 필요한 유틸리티 함수들을 작성합니다.
1. Redux 설정
1-1 모든 회원 목록 fetch - Redux Slice: 회원 상태 관리
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";
const serverUrl = import.meta.env.VITE_API_URL;
const memberSlice = createSlice({
name: "member",
initialState: {
user: null, // 현재 로그인한 사용자 정보
users: [], // 전체 사용자 목록
},
reducers: {
userLogin(state, action) {
state.user = action.payload;
sessionStorage.loging = JSON.stringify({
userNo: action.payload.userNo,
email: action.payload.email,
});
},
localUser(state, action) {
state.user = action.payload;
},
userLogout(state) {
state.user = null;
sessionStorage.clear();
},
initUsers(state, action) {
state.users = action.payload;
},
},
});
export const { userLogin, userLogout, localUser, initUsers } = memberSlice.actions;
export const fetchUsers = () => (dispatch) => {
axios
.get(`${serverUrl}/auth/users`)
.then((res) => {
dispatch(initUsers(res.data));
})
.catch((err) => console.log(err));
};
export default memberSlice.reducer;
1-2 모든 게시물 목록 fetch - Redux Slice: 피드 상태 관리
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";
const serverUrl = import.meta.env.VITE_API_URL;
const feedSlice = createSlice({
name: "feed",
initialState: {
feeds: [], // 전체 피드 목록
loading: false, // 로딩 상태
error: null, // 에러 상태
},
reducers: {
initFeedStart(state) {
state.loading = true;
state.error = null;
},
initFeedSuccess(state, action) {
state.feeds = action.payload;
state.loading = false;
},
initFeedFail(state, action) {
state.error = action.payload;
state.loading = false;
},
},
});
export const { initFeedStart, initFeedSuccess, initFeedFail } = feedSlice.actions;
export const fetchAllFeed = () => (dispatch) => {
dispatch(initFeedStart());
axios
.get(`${serverUrl}/feed/all`)
.then((res) => {
dispatch(initFeedSuccess(res.data));
})
.catch((err) => dispatch(initFeedFail(err)));
};
export default feedSlice.reducer;
2. 검색 컴포넌트 (SearchComponent)
1-1 초기 데이터 로드
useEffect(() => {
if (currentUser) {
dispatch(fetchFollowingList(currentUser.userNo));
}
dispatch(fetchUsers());
dispatch(fetchAllFeed());
}, [dispatch, currentUser]);
- fetchFollowingList, fetchUsers, fetchAllFeed는 각각 팔로우 목록, 사용자 목록, 전체 피드 목록을 서버에서 가져옵니다.
1-2 검색어와 검색 유형에 따른 필터링
useEffect(() => {
if (searchType === "user") {
const userResults = allUsers.filter(
(user) =>
user.userNo !== currentUser.userNo &&
user.userNickname.toLowerCase().includes(searchTerm.toLowerCase())
);
setFilteredUsers(userResults);
setFilteredFeeds([]);
} else {
const feedResults = allFeeds.filter((feed) => {
if (searchType === "hashtag") {
return feed.feedHashtags.some((hashtag) =>
hashtag.toLowerCase().includes(searchTerm.toLowerCase())
);
} else if (searchType === "location") {
return (
(feed.locationName &&
feed.locationName
.toLowerCase()
.includes(searchTerm.toLowerCase())) ||
(feed.weatherInfo &&
feed.weatherInfo.toLowerCase().includes(searchTerm.toLowerCase()))
);
}
return false;
});
setFilteredFeeds(feedResults);
setFilteredUsers([]);
}
}, [searchTerm, searchType, allUsers, allFeeds, currentUser]);
- useEffect는 검색어(searchTerm)와 검색 유형(searchType)이 변경될 때마다 필터링을 수행합니다.
- allUsers와 allFeeds에서 검색어에 해당하는 결과를 필터링하여 setFilteredUsers와 setFilteredFeeds로 상태를 업데이트합니다.
2-3 슬라이더 및 검색 버튼 설정
const settings = {
dots: true,
infinite: false,
speed: 500,
slidesToShow: 1,
arrows: false,
};
const goToSlide = (index) => {
if (sliderRef.current) {
sliderRef.current.slickGoTo(index);
}
setCurrentSlide(index);
if (index === 0) setSearchType("user");
else if (index === 1) setSearchType("hashtag");
else if (index === 2) setSearchType("location");
};
- goToSlide는 슬라이더 이동 함수로, 슬라이더 인덱스에 따라 검색 유형(searchType)을 변경합니다.