TIL 31 | fetch data

dabin *.โ—Ÿ(หŠแ—จห‹)โ—ž.*ยท2021๋…„ 9์›” 6์ผ
0

React

๋ชฉ๋ก ๋ณด๊ธฐ
5/14
post-thumbnail
post-custom-banner

json ํŒŒ์ผ

์•„๋ž˜์™€ ๊ฐ™์ด key๊ฐ’ ๋ชจ๋‘ ""๋กœ ์ž‘์„ฑํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

{
	"data": [{
			"id": 101,
			"category": "์ฝœ๋“œ ๋ธŒ๋ฃจ",
			"name": "์•„์ด์Šคํฌ๋ฆผ ๋ธ”๋ Œ๋”ฉ ์ฝœ๋“œ ๋ธŒ๋ฃจ",
			"engName": "Ice Cream Blending Cold Brew",
			"summary": "",
			"desc": "",
			"imgUrl": "",
			"servingSize": "Tall(ํ†จ) / 355ml (12 fl oz)",
			"kcal": "420",
			"fat": "6",
			"protein": "53",
			"natrium": "140",
			"sugars": "53",
			"caffeine": "210",
			"allergen": "๋Œ€๋‘ / ์šฐ์œ "
		},
		{
			"id": 102,
			"category": "์ฝœ๋“œ ๋ธŒ๋ฃจ",
			"name": "๋‚˜์ดํŠธ๋กœ ๋ฐ”๋‹๋ผ ํฌ๋ฆผ",
			"engName": "Nitro Vanilla Cream",
			"summary": "",
			"desc": "",
			"imgUrl": "",
			"servingSize": "Tall(ํ†จ) / 355ml (12 fl oz)",
			"kcal": "75",
			"fat": "2",
			"protein": "1",
			"natrium": "20",
			"sugars": "10",
			"caffeine": "245",
			"allergen": "์šฐ์œ "
		}
    ]
}

mock data๋กœ ํ™œ์šฉํ•ด๋ณด๊ธฐ!

fetch()ํ•จ์ˆ˜์—์„œ default ๋ฉ”์„œ๋“œ๋Š” GET์ด๋‹ค.


constructor() {
	super();
	this.state = {
		products: [],
	}
}

componentDidMount() {						
  fetch('http://localhost:3000/data/myData.json', { method: 'GET'
	})
	.then(res => res.json())
    .then(data => {
        this.setState({
          	products: data.data,     
        });
     });
}

json ๋ฐ์ดํ„ฐ์˜ 'data'๋ฅผ products์— ๋‹ด์•˜๊ธฐ ๋•Œ๋ฌธ์— products ๋ฐฐ์—ด์—๋Š” [{id:101, ...}, {id:102, ...}]๊ฐ€ ๋‹ด๊ธฐ๊ฒŒ ๋˜๊ณ , renderํ•จ์ˆ˜ ์•ˆ์—์„œ {this.state.producs}๋กœ ์ ‘๊ทผํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

์ฒซ ๋ฒˆ์งธ then ํ•จ์ˆ˜์— ์ „๋‹ฌ๋œ ์ธ์ž res๋Š” http ํ†ต์‹  ์š”์ฒญ๊ณผ ์‘๋‹ต์—์„œ ์‘๋‹ต์˜ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด(Response Object)๊ณ , ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” json ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  return ํ•ด์•ผ ํ•œ๋‹ค. ์ดํ›„ ๋‘ ๋ฒˆ์งธ then์—์„œ ์‘๋‹ต body์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

๋ฐฑ์—”๋“œ์—์„œ ์‘๋‹ต body๋ฅผ ์ฃผ์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค. ์ด ๋•Œ json()์„ ํ˜ธ์ถœํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค. ์ด ๊ฒฝ์šฐ res.status๋กœ ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜๊ณ (200, 403 ๋“ฑ) then ์•ˆ์—์„œ if๋ฌธ์„ ์‚ฌ์šฉํ•ด body๋ฅผ ๋ฐ›์€ ๊ฒฝ์šฐ์™€ ๋ฐ›์ง€ ์•Š์€ ๊ฒฝ์šฐ๋กœ ๋‚˜๋ˆ„์–ด returnํ•˜๋ฉด ๋œ๋‹ค.

ํ•œ ๊ฐ€์ง€ ์˜๋ฌธ, fetch๋Š” ํ•ญ์ƒ componentDidMount์—์„œ ํ•ด์•ผ ํ• ๊นŒ?

๋ฆฌ์•กํŠธ๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋…ธ๋“œ๋‚˜ ์Šคํ”„๋ง ๊ฐ™์€ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋ฅผ ์ด์šฉํ•ด ๋งŒ๋“ค์–ด์ง„ ์›น์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„๋œ๋‹ค. ์„œ๋ฒ„์— API๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด Life cycle์„ ์ดํ•ดํ•ด๋ณด์ž.

//์ƒ์„ฑ ๋  ๋•Œ
constructor()
componentWillMount()
render()
componentDidMount()

//update
shouldComponentUpdate()
- ์ปดํฌ๋„ŒํŠธ์˜ ๋ฐ์ดํ„ฐ์™€ ํ™”๋ฉด์— ์ถœ๋ ฅ๋œ ๋‚ด์šฉ์ด ๋‹ค๋ฅผ ๋•Œ ๋™์ž‘, ๊ธฐ๋ณธ์ ์œผ๋กœ true ๋ฐ˜ํ™˜
componentWillUpdate()
render()
componentDidUpdate()
- ํ™”๋ฉด์— ์ถœ๋ ฅ๋˜๋Š” ํ™”๋ฉด ๊ตฌ์„ฑ์„ ๋ณ€๊ฒฝํ•˜๊ณ ์ž ํ•  ๋•Œ ๋งŽ์ด ์‚ฌ์šฉ

//์ปดํฌ๋„ŒํŠธ ํ•ด์ œ
componentWillUnmount()
- ์ปดํฌ๋„ŒํŠธ์˜ ๋™์ž‘์„ ์œ„ํ•ด ์‚ฌ์šฉ๋˜์—ˆ๋˜ ๋ฉ”์†Œ๋“œ๋“ค์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ฑฐ
- ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€ ํ•จ์ˆ˜

componentDidMount์—์„œ API๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํšจ๊ณผ์ ์ด๋‹ค.

์™œ๊ทธ๋Ÿด๊นŒ? componentDidMount๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ๋ฐœ์ƒํ•œ๋‹ค. props๋‚˜ state๊ฐ€ ๋ฐ”๋€Œ๋Š” ๋“ฑ ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธฐ๋ฉด componentDidUpdate๊ฐ€ ๊ณ„์† ๋ถˆ๋ฆฌ๊ฒŒ ๋˜๋Š”๋ฐ, ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ๋ณ€ํ™”๊ฐ€ ์—†๋Š” ๋ฐ์ดํ„ฐ๋„ ๊ณ„์† ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์™€์•ผํ•˜๋‹ˆ๊นŒ ํ•„์š”์—†๋Š” ์ผ์„ ํ•˜๋Š” ๊ฒƒ์ด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ componentDidMount์—์„œ ํ•˜๋Š” ๊ฒƒ์ด ์œ ๋ฆฌํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

constructor ํ•จ์ˆ˜๋„ ์ƒ์„ฑ๋  ๋•Œ๋งŒ ํ˜ธ์ถœ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์—๋Š” ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์žˆ์„๊นŒ? ๋ฆฌ์•กํŠธ ๋ผ์ดํ”„ ์‚ฌ์ดํด์—์„œ render ์ดํ›„ DOM์— ์—…๋ฐ์ดํŠธ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค. ๋งŒ์•ฝ constructor์—์„œ API๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด ๋ฐ์ดํ„ฐ๋Š” fetch๊ฐ€ ๋˜๊ฒ ์ง€๋งŒ, ์ปดํฌ๋„ŒํŠธ๋Š” DOM์— ์•„์ง ์กด์žฌํ•˜๋Š” ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๊ฒŒ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ DOM์ด ์—…๋ฐ์ดํŠธ ๋œ ์ƒํƒœ์—์„œ fetch ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ๊ฒƒ ๊ฐ™๋‹ค.

๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ์™€ ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์—์„œ?

user Id๊ฐ€ props๋ฅผ ํ†ตํ•ด ๋„˜์–ด์˜จ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด fetch๋ฌธ ์•ˆ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

class User extends Component {
  componentDidMount() {
    const { userId } = this.props;
    fetch(`https://api.google.com/user/${userId}`)
      .then(res => res.json())
      .then(res => {
        if (res.success) {
            console.log(`${res.user.name}` ๋‹˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค);
        }
      });
  }
}

GET ๋ฉ”์„œ๋“œ ๋ง๊ณ  POST ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ๋Š” ์ „๋‹ฌํ•ด์•ผ ํ•  ๋ฉ”์„ธ์ง€๊ฐ€ ์กฐ๊ธˆ ๋” ๊ธธ์–ด์ง„๋‹ค. ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ๋ฅผ body์— ์ž‘์„ฑํ•˜๋Š”๋ฐ JSON ํ˜•ํƒœ๋กœ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•˜๋‹ˆ stringify๋กœ JSON ํ˜•์‹์— ๋งž๊ฒŒ ๋ฐ”๊พธ์–ด ์ค€๋‹ค.

fetch('https://api.google.com/user', {
    method: 'post',
    body: JSON.stringify({
        name: "dabin",
        batch: 1
    })
  })
  .then(res => res.json())
  .then(res => {
    if (res.success) {
        alert("์ €์žฅ ์™„๋ฃŒ");
    }
  })

์œ„๋ฒ…์Šค ๋””ํ…Œ์ผ ํŽ˜์ด์ง€์— ๊ฐ ์ปคํ”ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ fetch ํ•จ์ˆ˜์—๋Š” this.props.match.params.id๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

<Route
        exact
        path="/list-dabin/detail-dabin/:id"
        component={detailDabin}
      />

๊ฒฝ๋กœ๋ฅผ :id๋กœ ๋ฐ์ดํ„ฐ์˜ id๊ฐ’์— ๋”ฐ๋ผ ๋ณ€ํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๊ณ , ์ด id๊ฐ’์ด JSON ๋ฐ์ดํ„ฐ์˜ id๊ฐ’์ด ์ผ์น˜ํ•  ๋•Œ ๊ทธ ๊ฐ์ฒด๋งŒ ํ•˜๋‚˜ ๋“ค๊ณ ์˜ค๋„๋ก ๋งŒ๋“ค์–ด์„œ ์ปคํ”ผ๋ณ„ ์ƒ์„ธํŽ˜์ด์ง€๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค.

constructor() {
    super();
    this.state = {
      details: {},
    };
  }

  componentDidMount() {
    const id = this.props.match.params.id * 1;
    console.log(id);
    fetch('http://localhost:3000/data/detailMockData.json', {
      method: 'GET',
    })
      .then(res => res.json())
      .then(data => {
        this.setState({
          details: data.data.filter(detail => detail.id === id)[0],
        });
      });
  }

fetch๋กœ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๋ฅผ map ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, ๋งŒ์•ฝ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์„œ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค์ง€ ๋ชปํ–ˆ์„ ๋•Œ๋ฅผ ์œ„ํ•ด ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ๋งŒ์•ฝ ๋ฐ์ดํ„ฐ๊ฐ€ undefined๋ผ๋ฉด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๋„๋ก ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•ด๋†“๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์ด ์žˆ๋Š”๋ฐ, ์˜ˆ๋ฅผ ๋“ค๋ฉด if๋ฌธ์„ ์‚ฌ์šฉํ•œ๋‹ค๊ฑฐ๋‚˜ optional chaining(?.)์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค
optional chaining ์—ฐ์‚ฐ์ž
?. ์—ฐ๊ฒฐ๋œ ๊ฐ์ฒด ์ฒด์ธ ๋‚ด์— ๊นŠ์ˆ™์ด ์œ„์น˜ํ•œ ์†์„ฑ ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ์ฐธ์กฐ๊ฐ€ null ๋˜๋Š” undefined๋ผ๋ฉด, ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ ๋Œ€์‹  ํ‘œํ˜„์‹์˜ ๋ฆฌํ„ด ๊ฐ’์€ undefined๊ฐ€ ๋œ๋‹ค.
์ฐธ์กฐ๊ฐ€ ๋ˆ„๋ฝ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, ์–ด๋–ค ์†์„ฑ์ด ํ•„์š”ํ•œ์ง€ ๋ณด์ฆ์ด ํ™•์‹คํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์งง๊ณ  ๊ฐ„๋‹จํ•œ ํ‘œํ˜„์‹์œผ๋กœ ๊ฐ์ฒด์˜ ๋‚ด์šฉ์„ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

const customer = {
  name: 'dabin',
  laptop: {
    name: 'macBook'
  }
};
const keyboardName = adventurer.keyboard?.name;
console.log(keyboardName);
//undefined. 
profile
๋ชจ๋ฅด๋Š”๊ฒƒํˆฌ์„ฑ์ด
post-custom-banner

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