[๐Ÿ’ป ์ฝ”๋“œ์Šคํ…Œ์ด์ธ  FE 44๊ธฐ] ์†”๋กœ ํ”„๋กœ์ ํŠธ - ๋ (์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ, ๋ถ๋งˆํฌ ๋ฆฌ์ŠคํŠธ ๊ตฌํ˜„)

JiEunยท2023๋…„ 5์›” 18์ผ
0

โœ”๏ธ ์‹œ์ž‘

๋งˆ์ง€๋ง‰์ธ ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ, ๋ถ๋งˆํฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ๋‹ค.
์žฌ์‚ฌ์šฉ์ด ์žˆ๋Š” ์ƒํ’ˆ ์ปดํฌ๋„ŒํŠธ ์ž‘์—…์„ ๋งˆ๋ฌด๋ฆฌํ•˜๋‹ˆ ๋‚˜๋จธ์ง€๋Š” ๊ทธ๋ž˜๋„ ๋งŽ์€ ์‹œ๊ฐ„?์„ ๋“ค์ด์ง€ ์•Š์•˜์•˜๋˜๊ฑฐ ๊ฐ™๋‹ค.


๐Ÿ“ ์ž‘์—… ํ˜„ํ™ฉ

์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ, ๋ถ๋งˆํฌ ๋ฆฌ์ŠคํŠธ์— ํŽ˜์ด์ง€๋Š” ๊ตฌ์กฐ๊ฐ€ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค๋ฉด ๊ฑฐ์˜ ๋๋‚ฌ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

โœ”๏ธ ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ ํŽ˜์ด์ง€


์ƒ๋‹จ์— ํƒญ๋ฉ”๋‰ด๊ฐ€ ์žˆ๊ณ  ํ•ด๋‹น ๋ฉ”๋‰ด๋ฅผ ํด๋ฆญ ์‹œ ํ•„ํ„ฐ๋ง ๋˜์–ด์„œ ์•„๋ž˜ ํ™”๋ฉด์ด ๋‚˜์˜จ๋‹ค.

โœ”๏ธ ํƒญ ๋ฉ”๋‰ด ๊ตฌํ˜„

๋งจ์ฒ˜์Œ ๋“ค์—ˆ๋˜ ์ƒ๊ฐ์€ ๋ผ์šฐํ„ฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ธˆ๋ฐฉํ•˜๊ฒ ๋‹ค! ์ƒ๊ฐํ–ˆ๋‹ค.

๊ทผ๋ฐ ์™ ๊ฑธ? ์ƒ๊ฐ ๋ณด๋‹ค ๋‚ด๊ฐ€ ์›ํ•˜๋Š”๋Œ€๋กœ ๊ตฌํ˜„ ๋˜์ง€๋„ ์•Š์•˜๊ณ 
ํด๋ฆญ ํ–ˆ์„ ๋• ์•„๋ฌด๋Ÿฐ ํ™”๋ฉด๋„ ๋‚˜์˜ค์ง€ ์•Š์•˜๋‹ค.

์ด๋Ÿฌ๋‹ค ๋ผ์šฐํ„ฐ๋กœ ์‹œ๊ฐ„ ๋‚ญ๋น„ํ•˜๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‹ค ๊ตฌ๊ธ€๋ง ํ–ˆ์„ ๋•Œ ๊ฐ์ฒด ํ˜•์‹์„ ๋งŒ๋“ค์–ด ์ธ๋ฑ์Šค ๊ฐ’์— ๋”ฐ๋ผ ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ๋Š”๊ฒŒ ๋‚ด์šฉ์ด ์žˆ์—ˆ๋‹ค.
"์•„! ์ด๊ฑฐ๋‹ค!" ์‹ถ์—ˆ๋‹ค.

const [isTapmenu, setIsTapmenu] = useState(0)
const tabContArr = [
    { name: "์ „์ฒด", type: "all", src: imgAll, content: "1" },
    { name: "์ƒํ’ˆ", type: "brand", src: imgBrand, content: "2" },
    { name: "์นดํ…Œ๊ณ ๋ฆฌ", type: "category", src: imgCategory, content: "3" },
    { name: "๊ธฐํš์ „", type: "exhibition", src: imgExhibition, content: "4" },
    { name: "๋ธŒ๋žœ๋“œ", type: "product", src: imgProduct, content: "5" },
  ];

const handleFilter = (idx) => {
	setIsTapmenu(idx)
}
.
.
.
<TabListCont>
        {tabContArr.map((el, idx) => (
          <TabList key={idx} id={idx} tabContArr={el} isTapmenu={isTapmenu} handleFilter={handleFilter} />
        ))}
</TabListCont>
<div>
	{tabContArr[isTapmenu].content}
</div>

isTapmenu๋Š” ํƒญ๋ฉ”๋‰ด์˜ ์ธ๋ฑ์Šค ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.
tabContArr๋Š” ํƒญ๋ฉ”๋‰ด์˜ ์ด๋ฆ„, ํƒ€์ž…, ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ, ์ปจํ…์ธ (ํ…Œ์ŠคํŠธ์šฉ)์„ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ๋‹ค.

map()๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ํ™”๋ฉด์— ๋ณด์ด๋„๋ก ์ž‘์—…ํ–ˆ๋‹ค.
๋ฒ„ํŠผ ํด๋ฆญ์‹œ handleFilter์˜ ์ธ์ž์— ์ธ๋ฑ์Šค ๊ฐ’์ด ์ „๋‹ฌ๋˜์–ด ํ•ด๋‹น ์ธ๋ฑ์Šค ๊ฐ’์— ๋งž์ถฐ ์ปจํ…์ธ  ๋‚ด์šฉ์ด ๋ณ€๊ฒฝ ๋˜๋„๋ก ์ง„ํ–‰ํ–ˆ๋‹ค.

์ด๊ฑฐ ํ•˜๋‚˜ ์™„์„ฑํ–ˆ๋Š”๋ฐ ๋˜๊ฒŒ ๋ฟŒ๋“ฏํ–ˆ๋‹ค ใ…Žใ…Ž

โœ”๏ธ ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ ๋ฟŒ๋ฆฌ๊ธฐ

์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ๋Š” ์ƒํ’ˆ์˜ ํƒ€์ž…์„ ํ•„ํ„ฐ๋งํ•ด์„œ ํ™”๋ฉด์— ๋…ธ์ถœ์‹œํ‚ค๋ฉด ๋˜๊ฒ ๋‹ค ์ƒ๊ฐํ–ˆ๋‹ค.
์กฐ๊ฑด๋ฌธ์„ ์ค˜์„œ productItem์š”์†Œ์˜ type์ค‘ tabContArr๊ฐ ์š”์†Œ์˜ type๊ณผ ์ผ์น˜ํ•˜๋Š” ์ƒํ’ˆ์ด ์žˆ์„ ๊ฒฝ์šฐ filterItem์— ๋‹ด๊ณ  ์ด๋ฅผ ํ™”๋ฉด์— ๋ณด์—ฌ์ฃผ๊ฒŒํ•˜๋ ค๊ณ  ํ–ˆ๋‹ค.

์ผ๋‹จ ํด๋ฆญ ์‹œ ์ž˜ ๋ณด์˜€์ง€๋งŒ ๋‘๋ฒˆ ํด๋ฆญ ํ•ด์•ผํ•˜๋Š” ๋ฌธ์ œ์ ์ด ์žˆ์—ˆ๋‹ค.
์ด ๋•Œ useEffect()๋ฅผ ์‚ฌ์šฉํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

const [isFilterType, setIsFilterItem] = useState('')
const [filterItem, setFilterItem] = useState(productItem)
const [isTapmenu, setIsTapmenu] = useState(0)

 const tabContArr = [
    { name: "์ „์ฒด", type: "all", src: imgAll, content: "1" },
    { name: "์ƒํ’ˆ", type: "brand", src: imgBrand, content: "2" },
    { name: "์นดํ…Œ๊ณ ๋ฆฌ", type: "category", src: imgCategory, content: "3" },
    { name: "๊ธฐํš์ „", type: "exhibition", src: imgExhibition, content: "4" },
    { name: "๋ธŒ๋žœ๋“œ", type: "product", src: imgProduct, content: "5" },
  ];

const handleFilter = (idx, type) => {
	setIsTapmenu(idx);
	setIsFilterItem(type);
};

  useEffect(() => {
    if (filterItem.length === 0) {
      setFilterItem(productItem)
    }
    let filteredItem = productItem.filter((el) => tabContArr[isTapmenu].type === el.type);
    setFilterItem([...filteredItem]);
  }, [isTapmenu]);

๊ฐ๊ฐ์˜ ํƒญ๋ฉ”๋‰ด ํด๋ฆญ์‹œhandleFilter ํ•จ์ˆ˜๊ฐ€ ์ง„ํ–‰๋œ๋‹ค.
useEffect์—์„œ isTapmenu์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ ๋  ๋•Œ ์‹คํ•ดํ•˜๋„๋ก ์ง„ํ–‰ํ–ˆ๋‹ค.

๊ทธ๋žฌ๋”๋‹ˆ ๋‘๋ฒˆ ํด๋ฆญํ•ด์•ผํ•˜๋Š” ์ ์šฉ๋˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

useEffect์ž˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์„œ ํ๋ฆ„ ํŒŒ์•…์ด ์–ด๋ ค์› ๋Š”๋ฐ
์ด๋ฒˆ ๊ธฐํšŒ๋ฅผ ํ†ตํ•ด ์–ด๋Š ์ •๋„ ์ดํ•ด ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ ๊ฑฐ ๊ฐ™๋‹ค.

์™„์„ฑ๋˜๋Š” ํ™”๋ฉด์„ ๋ณด๋‹ˆ ๋ฟŒ๋“ฏํ•˜๋‹ค ใ…Žใ…Žใ…Ž
์ƒํ’ˆ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ™”๋ฉด์ด ๊นœ๋ฐ•์ด๋Š” ์ด์Šˆ๊ฐ€ ์žˆ๋‹ค.

์ด๊ฑด ๋‚˜์ค‘์— ๋กœ๋”ฉํ™”๋ฉด์„ ์ถ”๊ฐ€ํ•ด ์ฃผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค. (์ด๊ฑด ์š”๊ตฌ์‚ฌํ•ญ์— ์—†๋Š” ๋‚ด์šฉ์œผ๋กœ ์ถ”ํ›„ ์—…๋ฐ์ดํŠธํ•ด๋ณด๋ฉด ์ข‹์„ ๋“ฏ ์‹ถ๋‹ค.)

โœ”๏ธ ๋ถ๋งˆํฌ ๋ฆฌ์ŠคํŠธ

๋ถ๋งˆํฌ ๋ฆฌ์ŠคํŠธ๋Š” ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ์™€ ์Šคํƒ€์ผ์ด๋‚˜ ๊ตฌ์กฐ๊ฐ€ ๋™์ผํ•ด
์˜ค๋žœ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ์ง€ ์•Š์•˜๋‹ค.

์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ ์˜์—ญ์— localStorage์— ์ €์žฅ๋œ ์ƒํ’ˆ์„ ๊ตฌ๋ถ„ ์ง“๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ๋‹ค.

  useEffect(() => {
    if (filterItem.length === 0) {
      setFilterItem(productItem)
    } else if (storedData.length === 0) {
      setFilterStoredItem(storedData)
    }
    let filteredItem = productItem.filter((el) => tabContArr[isTapmenu].type === el.type);
    let filterStoredItem = storedData.filter((el) => tabContArr[isTapmenu].type === el.type);
    setFilterItem([...filteredItem]);
    setFilterStoredItem([...filterStoredItem]);
  }, [isTapmenu]);

filteredItem๋Š” ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ
filterStoredItem๋Š” localStorage์— ์ €์žฅ๋œ ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ์ด๋‹ค.

์ด๋ ‡๊ฒŒ ์ž‘์—…ํ•ด ์ฃผ๊ณ 
filterStoredItem๋ฅผ map()์„ ์ด์šฉํ•ด ํ™”๋ฉด์— ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.


์˜์ƒ ์šฉ๋Ÿ‰ ๋งˆ๋‹ค gif ์‚ฌ์ด์ฆˆ๊ฐ€ ์ž‘์€์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค...

๊ทธ๋ ‡๊ฒŒ ๋ถ๋งˆํฌ ๋ฆฌ์ŠคํŠธ ํŽ˜์ด์ง€๋„ ๊ตฌํ˜„ ์™„๋ฃŒ!

[์š”๊ตฌ์‚ฌํ•ญ]

  • ๋ถ๋งˆํฌ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ† ์ŠคํŠธ ์•Œ๋žŒ ์ฐฝ ๋‚˜์˜ค๊ธฐ
  • ๋ฌดํ•œ ์Šคํฌ๋กค ๊ตฌํ˜„

์ด ๋‘ ๊ฐ€์ง€๋Š” ์ฃผ์–ด์ง„ ๊ธฐ๊ฐ„ ์•ˆ์— ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.

ํ˜„์žฌ ๋‚ด๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„๊นŒ์ง€ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๊ณผ ๊นƒํ—™์— ๋Œ€ํ•ด ๋ฐฐ์šด ๊ฒƒ์— ์˜๋ฏธ๋ฅผ ๋‘์—ˆ๋‹ค.
๊ทธ๋ž˜์„œ ์ด ํ”„๋กœ์ ํŠธ๋Š” ๋ฆฌ๋•์Šค๊ฐ€ ์•„๋‹Œ useState๋กœ ๊ด€๋ฆฌ๋˜์–ด props๋กœ ๋•์ง€ ๋•์ง€ ๋ถ™์–ด ์žˆ๋‹ค.

๋ฆฌ๋•์Šค์— ์ข€ ๋” ์ต์ˆ™ํ•ด์ง„ ๋‹ค์Œ ๋ฆฌํŒฉํ† ๋งํ•ด๋„ ๊ดœ์ฐฎ๊ฒ ๋‹ค ์ƒ๊ฐํ–ˆ๋‹ค.

๊ทธ ๋•Œ ํ† ์ŠคํŠธ ์•Œ๋žŒ์ฐฝ๊ณผ ๋ฌดํ•œ ์Šคํฌ๋กค๋„ ๊ฐ™์ด ๊ตฌํ˜„ํ•˜๋ฉด ์ข‹๊ฒ ๋‹ค ์ƒ๊ฐํ•œ๋‹ค.
.
.
.

๋ฒˆ์™ธ


gif ํ™”๋ฉด ๋„ˆ๋ฌด ์ž‘๊ธด ํ•œ๋ฐ...
๋ถ๋งˆํฌ ์ƒํ’ˆ์ด ์•„๋ฌด๊ฒƒ๋„ ์—†์œผ๋ฉด ๋น„์–ด์žˆ์–ด์„œ
๋ถ๋งˆํฌ ์ƒํ’ˆ์ด ์—†์„ ๊ฒฝ์šฐ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.


โœ๏ธ ๋งˆ์น˜๋ฉฐ

์ด๋ฒˆ ์†”๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํ˜ผ์ž ํ•˜๋‹ค ๋ณด๋‹ˆ ๋ฌธ์ œ๊ฐ€ ๋‹ฅ์ณค์„ ๋•Œ
์˜ค๋žœ ์‹œ๊ฐ„์ด ๊ฑธ๋ ธ๋˜๊ฑฐ ๊ฐ™๋‹ค.

์ค‘๊ฐ„ ์ค‘๊ฐ„ ํŽ˜์–ด ํ™œ๋™์—์„œ ํŽ˜์–ด๋‹˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์ข‹์•˜๋‹ค.

๋˜ํ•œ ์ฃผ์–ด์ง„ ์กฐ๊ฑด์„ ์ „๋ถ€ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค. ์‹œ๊ฐ„์ด ๋ถ€์กฑํ•˜๊ธฐ๋„ ํ–ˆ๊ณ  ์•„์ง ๋‚ด ์‹ค๋ ฅ์—” ๋‚œ์ด๋„๊ฐ€ ๋†’์ง€ ์•Š์„๊นŒ ์‹ถ์—ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฆฌ๋•์Šค๋กœ ๊ด€๋ฆฌํ•˜๋Š”๊ฒŒ ์•„๋‹Œ useState๋ฅผ ์ด์šฉํ•ด ์ง„ํ–‰ํ•œ๊ฑฐ๋ผ props๊ฐ€ ๋•์ง€ ๋•์ง€ ๋ถ™์–ด ์žˆ์–ด ์ง€์ €๋ถ„ํ•˜๊ธฐ๋„ ํ•˜๋‹ค.

๋‚˜์ค‘์— ์‹œ๊ฐ„์„ ๋“ค์—ฌ ๋ฆฌํŒฉํ† ๋งํ•  ์˜ˆ์ •์ด๋‹ค.

๊ทธ ๋•Œ ๋ฒ„๊ทธ๋‚˜ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ–ˆ๋˜ ์  ๋“ฑ์„ ๊ฐ™์ด ์ง„ํ–‰ํ•ด ๋ณด๋ฉด ์ข‹๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

4์ผ ๋™์•ˆ ์งง์ง€๋งŒ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ฐ„์ ‘ ์ฒดํ—˜ํ•œ ๊ฒƒ ๊ฐ™๊ณ  ๊นƒํ—™ branch ๋“ฑ์— ๋Œ€ํ•ด ์ข€ ๋” ์•Œ ์ˆ˜ ์žˆ์—ˆ๋˜ ์‹œ๊ฐ„์ด์˜€๋‹ค.

๋‚จ์€ ๊ธฐ๊ฐ„๋„ ํž˜๋‚ด๋ณด์ž...

์†”๋กœ ํ”„๋กœ์ ํŠธ ๊นƒํ—™ ์ฃผ์†Œ

๐Ÿ”— https://github.com/jieun419/fe-sprint-coz-shopping

profile
๐Ÿ’ป ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋ชฉํ‘œ๋กœ ์„ฑ์žฅ ์ค‘! (์•Œ์•„๋ดค๋˜ ๋‚ด์šฉ ๋“ฑ์„ ์ •๋ฆฌํ•˜๊ธฐ)

0๊ฐœ์˜ ๋Œ“๊ธ€