๐ŸšŒ[RN]Kakao-bus(์นด์นด์˜ค ๋ฒ„์Šค) Clone ํ”„๋กœ์ ํŠธ

์„์ง„ยท2024๋…„ 1์›” 30์ผ
0
post-thumbnail
post-custom-banner

๐ŸšŒ์นด์นด์˜ค๋ฒ„์Šค clone ํ•ด๋ณด๊ธฐ

๐ŸšŒSectionList์™€ FlatList์™€์˜ ์ฐจ์ด

 <FlatList
          data={[
            { busNum: 146 },
            { busNum: 360 },
            { busNum: 740 },
            { busNum: 3412 },
            { busNum: 1100 },
            { busNum: 1700 },
          ]}
          renderItem={({ item }) => <Text>{item.busNum}</Text>}
        />
         <SectionList
          sections={[
            {
              title: "๊ฐ„์„ ๋ฒ„์Šค",
              data: [{ busNum: 146 }, { busNum: 360 }, { busNum: 740 }],
            },
            {
              title: "์ง€์„ ๋ฒ„์Šค",
              data: [{ busNum: 3412 }],
            },
            {
              title: "์งํ–‰๋ฒ„์Šค",
              data: [{ busNum: 1100 }, { busNum: 1700 }],
            },
          ]}
          renderSectionHeader={({ section: { title } }) => <Text>{title}</Text>}
          renderItem={({ item }) => <Text>{item.busNum}</Text>}
        />
        
        
  • FlatList๋Š” data ์•ˆ์— ๋ฐฐ์—ด์„ ๋„ฃ์–ด์คฌ์ง€๋งŒ SectionList๋Š” sections ๊ฐ€ ํ•„์š”
    ๊ทธ๋ฆฌ๊ณ  title, ๊ทธ ์•ˆ์—์„œ ๋ฐ˜๋ณต๋  data list ๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค.
  • Section ๋ถ€๋ถ„์„ ๋ Œ๋”ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” renderSectionHeader ๋ผ๋Š” prop์„ ํ™œ์šฉ

๐ŸšŒuseState, useEffect, setInterval ์„ ์ด์šฉํ•ด 1์ดˆ๋งˆ๋‹ค ๋„์ฐฉ์‹œ๊ฐ ์—…๋ฐ์ดํŠธ ํ•˜๊ธฐ

 const [now, setNow] = useState(dayjs());
 
  useEffect(() => {
  setInterval(() => {
    const newNow = dayjs();
    setNow(newNow);
  }, 1000);
}, []);
 
  • ๋งŒ๋“ค์–ด ์คฌ์œผ๋ฉด ์ข…๋ฃŒํ•˜๋Š”์‹œ์ ๋„ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

     useEffect(() => {
      const interval = setInterval(() => {
        const newNow = dayjs();
        setNow(newNow);
      }, 1000);
    
      return () => {
        clearInterval(interval);
      };
    }, []);
  • ์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ ํ•˜๋Š” ์‹œ์ ์— ์ž๋™์œผ๋กœ ํ•ด์ œ๋จ

๐ŸšŒSectionList - ListHeaderComponet

  • ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ตœ์ƒ๋‹จ์ด ์•ˆ์ „์˜์—ญ ๋‹ค์Œ์œผ๋กœ ๊ทธ๋ ค์ง€๊ฒŒ ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
    SafeAreaView -> View ๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.
  • header ์— root ๋ฅผ SafeAreaView ๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.
      const ListHeaderComponent = () => {
     return (
       <SafeAreaView
         style={{ backgroundColor: COLOR.GRAY_1, width: "100%", height: 200 }}
       ></SafeAreaView>
     );
    };  

๐ŸšŒItemSeparatorComponent

  • FlatList๋‚˜ SectionList์™€ ๊ฐ™์€ ๋ฆฌ์ŠคํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ฐ ์•„์ดํ…œ ์‚ฌ์ด์— ์œ„์น˜ํ•  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง€์ •ํ•˜๋Š” ํ”„๋กœํผํ‹ฐ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์•„์ดํ…œ๋“ค ์‚ฌ์ด์— ๊ตฌ๋ถ„์„ ์ด๋‚˜ ๊ณต๊ฐ„์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๊ธฐ๋ณธ์ ์œผ๋กœ ItemSeparatorComponent๋Š” ๋ฆฌ์ŠคํŠธ ๋‚ด๋ถ€์˜ ๊ฐ ์•„์ดํ…œ๋“ค ์‚ฌ์ด์— ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฆฌ์ŠคํŠธ์— ๋ฐ์ดํ„ฐ๊ฐ€ 10๊ฐœ ์žˆ์„ ๊ฒฝ์šฐ, ItemSeparatorComponent๋ฅผ ํ†ตํ•ด 9๊ฐœ์˜ ๊ตฌ๋ถ„์„ ์ด๋‚˜ ๊ณต๊ฐ„์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐ŸšŒSectionList - refreshControl

  • ScrollView, FlatList, SectionList ๋“ฑ์— ์Šคํฌ๋กค์ด ๊ฐ€๋Šฅํ•œ ๊ณณ์—์„œ ์‚ฌ์šฉ๊ฐ€๋Šฅ

    const [refreshing, setRefreshing] = useState(false);
      
       const onRefresh = () => {
      setRefreshing(true);
    };
    
    useEffect(() => {
    // ์ธ๋””์ผ€์ดํ„ฐ๊ฐ€ ๋ณด์ผ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ refetch ํ•ด์ค€๋‹ค.
      if (refreshing) {
        setNow(dayjs());
        setRefreshing(false);
      }
    }, [refreshing]);
      
      
      refreshControl={
            <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
          }
          
          
  • refresh ๋ฅผ ํ–ˆ์„ ๋•Œ api ์ธก์— data ๋ฅผ ๋‹ค์‹œ refetch ํ•ด๋‹ฌ๋ผ๋ผ๋Š” ์š”์ฒญ

  • refreshing ์ด true ์ผ ๋•Œ ์ธ๋””์ผ€์ดํ„ฐ ๊ฐ€ ๋ณด์ด๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ refetch ํ•ด์ค€๋‹ค.

  • data ๊ฐ€ refetch ๋˜๋ฉด setRefreshing(false)๋กœ ํ•ด์ค˜์„œ ์ธ๋””์ผ€์ดํ„ฐ๊ฐ€ ์‚ฌ๋ผ์ง€๋„๋ก

  • setRefreshing(false) ๋Š” api refetch ๊ฐ€ ์™„๋ฃŒ๋˜๋Š” ์‹œ์ 

๐ŸšŒ custom hook -useTheme(๋‹คํฌ๋ชจ๋“œ), Switch Component

import { useState } from "react";
import { DARK_COLOR, LIGHT_COLOR } from "./color";

const useTheme = () => {
const [isDark, setIsDark] = useState(false);

const toggleIsDark = () => setIsDark(!isDark);

return {
  NEWCOLOR: isDark ? DARK_COLOR : LIGHT_COLOR,
  toggleIsDark,
};
};

export default useTheme;

Switch Component

  <Switch value={isDark} onValueChange={toggleIsDark} />
  • ์Šค์œ„์น˜ Component ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ธฐ๋ณธ๊ฐ’์„ false ๋กœ ๋‘๊ณ  change ํ–ˆ์„ ๋•Œ !isDark ๋ฅผ ํ•ด์คŒ์œผ๋กœ์จ ๋‹คํฌ๋ชจ๋“œ ๊ตฌํ˜„
profile
๋‚ด ์„œ๋น„์Šค ๋งŒ๋“ค๊ธฐ
post-custom-banner

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