inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[리뉴얼] React로 NodeBird SNS 만들기

안녕하세요, 질문입니다..!

318

tjffldi123
0

안녕하세요 제로초님

제로초님의 노드버드 강의에 날씨 기능을 추가해서 작업을 해보고있습니다...

현재 제로초님의 강좌를 챕터 5 노드 연결 초반까지 진행해놓고 날씨 api 를 받아와서 뿌리고싶어서 작업중에 있습니다.

그런데 에러의 원인을 알 수가 없어서요..ㅜㅜ 제가 사가나 리듀서쪽에서 뭘 잘못한건지..

일단 코드를 보여드리겠습니다.. (컴포넌트, 리듀서, 사가 순 입니다)

 

import React, { useEffect, useMemo } from 'react';
import { Card, Spin, Space } from 'antd';
import styled from 'styled-components';
import { useDispatch, useSelector } from 'react-redux';
import { CALL_WEATHER_REQUEST } from '../reducers/weather';

const Weather = () => {
const dispatch = useDispatch();
const { weatherInfo, location, weatherCallLoading } = useSelector(
state => state.weather
);

// 스타일 컴포넌트를 준 부분은 불필요할거같아 뺏습니다 ㅎㅎ
 

const cardStyle = useMemo(() => ({ marginTop: 10 }), []);

useEffect(() => {
dispatch({
type: CALL_WEATHER_REQUEST
});
}, []);
console.log(`나야....${weatherInfo.name}`);

return (
<div>
<Card title='오늘의 날씨' style={cardStyle}>
<WeatherStyle>
{weatherCallLoading === false ? (
<div>
<WeatherIcon>
{/* <img
src={`/images/${weatherInfo.weather[0].main}.png`}
role='presentation'
/> */}
</WeatherIcon>
<div>
<p>
<span>{weatherInfo.name}</span>
{/* {weatherInfo.weather[0].description} */}
</p>
<p>{/* 현재 온도 <span>{weatherInfo.main.temp}°C</span> */}</p>
</div>
</div>
) : (
<Space size='middle'>
<Spin size='large' />
</Space>
)}
</WeatherStyle>
</Card>
</div>
);
};

export default Weather;

 

우선 날씨를 보여주는 컴포넌트 부분입니다.

주석을 준 부분이 에러를 일으키는 부분입니다. ㅠㅠ

그냥 weatherInfo.name 같이 object type 이 아닌 객체인 경우 에러를 일으키지않지만

weatherInfo.weather[0].description 같은 값은 이런 에러가 발생합니다.

 

우선 리듀서와 사가의 코드부터 이어서 보여드리고 에러에 대해 자세히 말씀드리겠습니다.

 

import produce from 'immer';

export const initialState = {
weatherCallLoading: false,
weatherCallDone: false,
weatherCallError: null,
weatherInfo: [],
location: {}
};

export const CALL_WEATHER_REQUEST = 'CALL_WEATHER_REQUEST';
export const CALL_WEATHER_SUCCESS = 'CALL_WEATHER_SUCCESS';
export const CALL_WEATHER_FAILURE = 'CALL_WEATHER_FAILURE';

export const callWeatherRequestAction = data => {
return {
type: CALL_WEATHER_REQUEST,
data
};
};

const dummyWeather = data => ({
...data
// city: data.location,
// temperature: '-5',
// weatherState: '비',
// icon: 'rain',
// comment: '눈사람 되겠어요.'
});

const reducer = (state = initialState, action) => {
return produce(state, draft => {
switch (action.type) {
case CALL_WEATHER_REQUEST:
draft.weatherCallLoading = true;
draft.weatherCallDone = false;
draft.weatherIcon = null;
break;
case CALL_WEATHER_SUCCESS:
draft.weatherCallLoading = false;
draft.weatherCallDone = true;
draft.weatherInfo = dummyWeather(action.data);
draft.weatherIcon = null;
break;
case CALL_WEATHER_FAILURE:
draft.weatherCallLoading = false;
draft.weatherCallError = action.error;
break;
default:
break;
}
});
};

export default reducer;

 

리듀서 부분입니다.

 

import axios from 'axios';
import {
all,
call,
fork,
put,
takeEvery,
takeLatest
} from 'redux-saga/effects';
import {
CALL_WEATHER_FAILURE,
CALL_WEATHER_REQUEST,
CALL_WEATHER_SUCCESS
} from '../reducers/weather';

function weatherAPI() {
// component 에서 지역선택값 받아오기
// const city = action;
// ** weatherkey 값 부분은 보이면 안될거같아 가렸습니닷...
return axios.get(
`https://api.openweathermap.org/data/2.5/weather?q=Seoul&appid=${weatherKey}&lang=kr&units=metric`
);
}

function* weather(action) {
// const today = datetime.datetime.today();

try {
const result = yield call(weatherAPI);
yield put({
type: CALL_WEATHER_SUCCESS,
data: result.data
});
console.log(result.data);
} catch (err) {
yield put({
type: CALL_WEATHER_FAILURE,
error: err.response.data
});
}
}

function* watchWeather() {
yield takeLatest(CALL_WEATHER_REQUEST, weather);
// yield takeEvery(CALL_WEATHER_REQUEST, weather);
}

export default function* weatherSaga() {
yield all([fork(watchWeather)]);
}

 

이렇게 까지 코드입니다.

에러는 앞서 말씀드린대로 object 가 아닌 데이터를 가져오면 잘 나오는데,

object 객체를 불러오면 다음과 같은 에러가 뜹니다...

 

다음과 같은 에러가 뜨면서 500에러와 함께 오픈 api 요청을 무지하게 하드라구요ㅠㅠ

굳이 object 가 아니여도

weatherInfo.main.temp 같은 객체도 에러가 뜨는거보면 두번 거쳐서 불러오는 게 문제인가 싶기도합니다ㅠ

그리고 신기한게 문제가 되는 코드를 주석처리하고 서버를 렌딩한 다음에

새로고침을 하지않고 주석을 풀고 저장을 하면 에러가 뜨지않고 아래 그림처럼 정상으로 화면에 보여집니다.

 

다음과 같이 잘 나와요...그런데 새로고침을 하면 500에러가 뜹니다...

 

새로고침을 하면 500에러가 뜨는거라

api 를 불러올 때 느려서 undefined 에서 찾으려고해서 500에러가 뜨는거라고 생각이 드는데요...

(weatherInfo 값을 콘솔을 찍어보니 처음 렌딩할때 undefined 가 두번 찍히더라구요, 그 다음 제대로 불러오고요)

 

그런데..api 불러올때 처음에 undefined 라서 그런거라면...왜 weatherInfo.name 값은 정상적으로 불러오면서...

그것보다 깊게 들어간 배열이나 객체값은 500 에러가 뜨는건지..ㅠ 잘 모르겠습니다...

제가 api를 잘 못 불러오고있는건지..ㅜㅜㅜ 머리가 터질거같아요...

 

아, 그리고 api 는 이렇게 되어있습니다

 

제 깃헙 주소는 이거입니다ㅠㅠ

https://github.com/haerim95/anonymous-caster

 

답변 1

1

제로초(조현영)

weather가 없을 때를 대응을 안 하신 것 같은데요? weather가 undefined인 상황이 있을겁니다.

0

tjffldi123

아앗 넵 weather 가 undefined 일때 대응을 해보겠습니다..!
그런데 한가지 궁금한점은 weatherInfo.name 같은 경우는 새로고침이나 서버 렌딩시 에러가 나지않고 렌딩되는데 weatherInfo.main.temp 처럼 깊게 들어가는 경우..? 두단계 뒤의 객체를 못읽는거 같아서요... 같은 api 인데 왜 두단계를 거친 데이터만 읽지 못하는걸까요...?ㅠㅠ 

0

tjffldi123

오..말씀하신대로 weatherInfo.main.temp 와 weatherInfo.weather[0] 가 undefined 일때 null 로 보이도록 작업했더니 500에러가 발생하지않습니다..! 정말 감사드립니다 제로초님 ㅜㅜㅜㅜ ㅠㅠ 
그런데 두단계 들어간 것은 500에러가 떴는데 단계를 거치지않는 weatherInfo.name 은 이러한 처리를 하지않아도 정상적으로 나오는거보면 api 를 불러올때 weatherInfo.main.temp 와 weatherInfo.weather[0] 가 더 느리게 불러와지기때문인가요?? 너무 궁금하네요 ㅠ 검색해도 나오질않아서 여쭤봅니다ㅠㅠ

0

제로초(조현영)

weatherInfo 까지는 존재하는데 그 아래가 없는겁니다.

0

tjffldi123

아 그런거였군요 ㅎㅎㅎ 감사합니다 제로초님 궁금증이 해결됐습니다ㅠㅠ 정말 감사합니다!