살려줘.. Cannot read properties of undefined
스펙
React, Redux toolkit, middleware
상황
axios로 받아온 값을 화면에 렌더링 해주려고 하니 자꾸만 값이 undefined라고 뜬다.
받아온 값은 콘솔에 잘 뜨는데 대체 뭐가 잘 못된걸까.
시도
이 에러가 뜨는 경우는 받아온 값이 아직 다 받아지기 전에 화면에 뿌려주려고 할 떄 빈번히 일어난다.
그래서 3가지를 먼저 시도해보았다.
1. &&연산자와 조건문
const PostDetail = () => {
const params = useParams();
const boardId = Number(params.postId);
const dispatch = useDispatch();
const post = useSelector((state) => state.postReducer);
useEffect(() => {
dispatch(getPostDetail(boardId));
}, []);
console.log(post); // 주목!!
return (
<PostDetailStyle>
{post ? (
<FormWrap>...
</FormWrap>
) : null}
</PostDetailStyle>
);
};
&& 연산자는 앞 뒤의 값이 모두 true이면 뒤에 있는 걸 실행하고,
앞의 값이 false라면 어느것도 실행하지 않는다.
이를 이용해서 post에 값이 없으면 화면에 뿌려주지않고,
post가 업데이트된 후에 리렌더링이 일어나면 그때 태그를 보여주면 잘 되지 않을까 했다.
실패.
2. useEffect
useEffect에서 의존성 배열을 쓰면 되지않을까?
한마디로 첫 렌더링 + 배열안에 값이 변화할 때만 코드를 실행해준다.
먼저 post를 배열에 넣어주고 변화(업데이트)가 생기면 useState로 업데이트가 이뤄지게 했다.
실패.
useEffect(()=> {
// set함수
}, [post])
3. state에 들어갈 초깃값 설정해주기
const [postInfo, setPostInfo] = useState([]);
const [postInfo, setPostInfo] = useState("");
const [postInfo, setPostInfo] = useState(null);
이렇게 초깃값을 설정해주면 어쩃든간에 값이 있기때문에 오류가 나지않는다고 한다.
실패.
근데 나는 post 안에 객체에 또 접근을 해야한다.
e.g.
post[0].postDetail.title
post[0].postDetail.name
post[0].postDetail.imageUrl
해결
Optional chaning
마침표 앞에 물음표를 사용하면 앞에 있는 값에 유효한 값이 없으면 undefined를 반환하고, 있으면 마침표 다음을 실행한다.
값이 있을 때만 마침표 뒤를 실행하기 때문에 오류를 방지 할 수 있다.
그래서 post객체 안에 접근하기 위해서 매 depth마다 옵셔널 체이닝을 설정해주었다.
결국 유효한 값이 하나라도 있으면 undefined를 반환하기 때문에
undeifined 일 때와 값이 나왔을 때 조건부로 렌더링을 시켰다.
결과는 대성공!
결론
값이 들어오기 전에 렌더링 시키려하면 에러가 뜬다.
원하는 데이터가 객체 안에 객체(depth N) 안에 있다면 옵셔널 체이닝으로 depth 별로 값이 유효한지 체크를 할 수 있다.
받아오는 데이터의 타입이 무엇인지에 따라 해결방법이 다양하다.
참고
https://velog.io/@nemo/react-error-cannot-read-property