๐Ÿ“ฐ Front-end/React Native

[React Native] Google Forms ํด๋ก  ํ”„๋กœ์ ํŠธ

s2ylvia 2024. 5. 3. 02:18

Google Forms Clone Project

 

0. TypeScript + React Native + Recoil๋กœ ๊ตฌํ˜„ํ•œ ํ† ์ด ํ”„๋กœ์ ํŠธ

  • 3์ผ๋™์•ˆ ํ˜ผ์ž์„œ Google Forms์˜ ์ตœ์†Œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„
  • Expo๋กœ React Native๋ฅผ ์„ค์น˜ํ•ด์„œ ์ž‘์—…
    • ๊ณผ๊ฑฐ ํ”„๋กœ์ ํŠธ๋Š” ์ง์ ‘ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ๋Œ๋ฆฌ๋ฉด์„œ ๊ตฌํ˜„ํ–ˆ๋Š”๋ฐ, ์ •๋ง ์—๋ฎฌ๋ ˆ์ดํ„ฐ ํ‚ฌ๋•Œ๋งˆ๋‹ค ๊ณ ์—ญ์ด์—ˆ๋‹ค.
    • Expo๋กœ ์ž‘์—…ํ•˜๋‹ˆ ์•„์ฃผ ๊ฐ„ํŽธํ–ˆ์œผ๋‚˜ ์ด๊ฒƒ๋„ ๋งŒ๋Šฅ์€ ์•„๋‹Œ๋“ฏ.. ๊ฐ‘์ž๊ธฐ ์‹คํ–‰ ์—๋Ÿฌ๊ฐ€ ๋– ์„œ ์• ๋จน์—ˆ๋‹ค.
  • Recoil๋กœ ๋ชจ๋“  state๋ฅผ ์ „์—ญ ๊ด€๋ฆฌ
  • StyleSheet๋กœ ์Šคํƒ€์ผ๋ง

 

1. ๊ธฐ๊ฐ„

  • 2024.05.17 ~ 19์ผ

 

2. ์Šคํƒ

  • TypeScript
  • React Native
  • Recoil
  • UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(์•ก์…˜ ์‹œํŠธ..)

 

3. ๊ตฌํ˜„ ์‚ฌํ•ญ

  • ์„ค๋ฌธ ์ž‘์„ฑ
  • ์„ค๋ฌธ ์ถ”๊ฐ€, ์‚ญ์ œ, ๋ณต์‚ฌ
  • ๋‹จ๋‹ต, ์žฅ๋ฌธ, ๊ฐ๊ด€์‹, ์ฒดํฌ๋ฐ•์Šค
  • ์„ค๋ฌธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ

 

4. ๊ธฐ์–ตํ•˜๊ณ ์‹ถ์€ ์ฝ”๋“œ ๋ฐ ์•„์‰ฌ์šด ์ 

 

์„ค๋ฌธ ๋ฆฌ์ŠคํŠธ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ํ•จ์ˆ˜

const updateSurveyList = (
    id: number,
    action: "toggleSwitch" | "inputFocus" | "inputBlur"
  ) => {
    const updatedSurveyList = surveyList.map((item) => {
      if (item.id === id) {
        switch (action) {
          case "toggleSwitch":
            return {
              ...item,
              isEnabled: !item.isEnabled,
            };
          case "inputFocus":
            return {
              ...item,
              titleInputFocus: true,
            };
          case "inputBlur":
            return {
              ...item,
              titleInputFocus: false,
            };
          default:
            return item;
        }
      }
      return item;
    });
    setSurveyList(updatedSurveyList);
  };

 

์„ค๋ฌธ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๊ฐ์ฒด๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด์ด๊ธฐ ๋•Œ๋ฌธ์—

๊ฐ์ฒด ์•ˆ์— ์†์„ฑ์„ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋ ค๋ฉด ์šฐ์„ , ๋ฆฌ์ŠคํŠธ๋ฅผ map์œผ๋กœ ์ˆœํšŒํ•ด์ค€๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํด๋ฆญํ•  ๋•Œ ๋„˜๊ฒจ์ค€ ํ•ด๋‹น ์„ค๋ฌธ id์™€ ๋™์ผํ•œ id์˜ ๊ฐ์ฒด๋ฅผ ์ฐพ์œผ๋ฉด ๋ณ€๊ฒฝํ•ด์„œ return ํ•ด์ฃผ๊ณ 

๋‚˜๋จธ์ง€๋Š” ๊ทธ๋Œ€๋กœ returnํ•ด์„œ ๋ณ€๊ฒฝ๋œ ๋ฆฌ์ŠคํŠธ๋ฅผ setState ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜.

 

์†”์งํžˆ ์ด๋Ÿฐ ๊ธฐ๋Šฅ๋“ค todo list ๋งŒ๋“ค ๋•Œ ํ•˜๋˜ ๊ฒƒ๋“ค์ธ๋ฐ ์˜ค๋žœ๋งŒ์— ํ”„๋กœ์ ํŠธ๋ฅผ ํ•ด๋ณด๋‹ˆ

์ด๊ฒƒ๋„ ๋ฒ„๋ฒ…๋ฒ„๋ฒ….. 

 

inline style ์‚ฌ์šฉ์„ ์ง€์–‘ํ•˜์ž

{survey.option === "๋‹จ๋‹ตํ˜•" && (
 <View style={{ borderBottomWidth: 1, width: 180, borderColor: "#E9E9E9"}}>
   <Text style={styles.optionText}>๋‹จ๋‹ตํ˜• ํ…Œ์ŠคํŠธ</Text>
</View>
)}

 

Stylesheet๋ฅผ ์ •์˜ํ•˜๋ฉด์„œ ์‚ฌ์šฉํ•ด๋†“๊ณ  ์™œ ์ด๋ ‡๊ฒŒ inline style์„ ์‚ฌ์šฉํ–ˆ์„๊นŒ?

๊ฐ€๋…์„ฑ์€ ๋–จ์–ด์ง€๊ณ , ์Šคํƒ€์ผ์„ ํ•œ ๊ณณ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์—†์ž–์•„..

๊ตฌํ˜„ํ•œ๋‹ค๊ณ  ์ •์‹ ์—†์–ด์„œ ๋„ˆ๋ฌด ์ด๋Ÿฐ๊ฑฐ์— ์‹ ๊ฒฝ์„ ์•ˆ์“ด ๊ฒƒ ๊ฐ™๋‹ค.

์•ž์œผ๋กœ๋Š” inline style์€ ์ง€์–‘ํ•˜๋„๋ก ํ•ด์•ผ๊ฒ ๋‹ค..

 

๋ณต์žกํ•œ ์ต๋ช…ํ•จ์ˆ˜๋Š” ์„ ์–ธํ•˜์—ฌ ์‚ฌ์šฉํ•˜์ž

<Pressable
  style={styles.actionButton}
  onPress={() => actionSheetRef.current?.show()}
>

 

onPress ํ”„๋กœํผํ‹ฐ ์•ˆ์— ๋ง‰ ์ ์ง€๋ง๊ณ  ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด ํ•จ์ˆ˜๋Š” ์„ ์–ธํ•ด์„œ ์‚ฌ์šฉํ•˜์ž.

 

style์€ style๋ผ๋ฆฌ, ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜๋ผ๋ฆฌ ๋นผ์„œ ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜์ž

 

๋ฆฌํ„ด๋ฌธ ์œ„์—๋Š” ํ•จ์ˆ˜๊ฐ€, ์•„๋ž˜์—๋Š” Stylesheet๋ฅผ ๋‘๋‹ˆ๊น ์ „์ฒด์ ์œผ๋กœ ํ•œ ํŒŒ์ผ ์•ˆ์— ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ๊ณ 

๊ฐ€๋…์„ฑ๋„ ์—†๊ณ  ๋‚˜์ค‘์— ์œ ์ง€๋ณด์ˆ˜ ํ•˜๊ธฐ๋„ ํž˜๋“ค์–ด๋ณด์ธ๋‹ค.

์•ž์œผ๋กœ๋Š” ๋”ฐ๋กœ ํŒŒ์ผ๋กœ ๋นผ์„œ import ํ•˜๋Š” ๊ฒŒ ๋” ์ข‹์„ ๊ฑฐ ๊ฐ™๋‹ค.