inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트

리액트 axios 데이터 받아와서 랜더링 질문드립니다

해결된 질문

2571

똘이77

작성한 질문수 7

0

useState로 postList라는 이름의 state를 선언한 후 axios를 통해 얻은 결과를 setPostList를 통해 postList에 업데이트 시키고 . 그러면 state가 변경되었으므로 새롭게 렌더링이 되고 -> return이 다시 불리며 -> 변경된 값을 화면에 업데이트 시켜줄 주는걸로 알고있는데

 

function PostList() {


  const [postList, setPostList] = useState([]);
  //const headers = { Authorization: `JWT ${jwtToken}` };

    const [{ data: originPostList, loading, error }, refetch] = useAxios({
    url: "/api/posts/",
    //headers
  });

  useEffect(() => {
    setPostList(originPostList);

    console.log("mouted");
  }, [originPostList]);


  console.log("loaded respaonse2 :", postList);

  return (
  <div>

      {postList && postList['results'].length === 0 && (
        <Alert type="warning" message="포스팅이 없습니다. :-(" />
      )}
      {postList &&
        postList['results'].map(post => (
          <Post post={post} key={post.id}  />
        ))}
    </div>
  );
}

export default PostList;

loaded respaonse2 : []

loaded respaonse2 : []

loaded respaonse2 : []

loaded respaonse2 : []

콘솔창에 이렇게 4번이 뜹니다

어쩔때는 postList에 데이터가 들어가서 나오는데

useEffect에서 셋 시켜서 데이터가 들어갔는데도 빈 데이터가 나오는지 궁굼합니다.

return 문에 postList 가져오는 구문을 없애면 제대로 들어가는데 예외처리를 했는데도 map 찾을수 없다는 에러가 뜹니다

그리고 Simple jwt 토큰 인증을 쓰지 않으면 데이터는 잘가져옵니다

 

python docker react django

답변 1

0

이진석

안녕하세요.

함수 컴포넌트 바로 아래 depth의 코드들은 해당 컴포넌트가 렌더링될 때마다 수행이 됩니다. 그러니 아직 setPostList에 의해서 데이터가 채워지기 전인데 PostList 컴포넌트의 상탯값이 바뀌는 등의 여러가지 이유로 재렌더링이 발생한다면 쓰신 loaded respaonse2 메세지는 여러 번 출력될 수 있습니다.

그리고 originPostList를 바라보는 useEffect에서는

- useAxios를 통해 받은 originPostList 상탯값의 초기값은 undefined이며, API 응답을 받게 되면 이 후에 상탯값이 변경되게 되겠죠.

- 그러니 originPostList를 바라보는 useEffect에 지정된 함수는 첫번째 호출에서 originPostList가 undefined일 때 호출이 됩니다. 그러니 useEffect 내에서 originPostList 값이 undefined가 아닐때 setPostList를 호출할 수 있도록 방어적으로 코드를 작성해주시는 것이 좋습니다.

Uncaught TypeError: Cannot read properties of undefined (reading 'map') 에러가 발생하신다면, 해당 객체에서 지원하지 않는 속성명을 참조하여 undefined를 읽어왔고 그 undefined에 대해서 .map 을 수행했기에 발생하는 오류입니다.

그 당시의 postList 정확한 값을 확인해보셔야 합니다. 예상하신 것과는 다른 형태의 객체이실 수도 있습니다. postList라고 한다면 Array 형태를 예상하셨을 수 있는 데, Array에 "results"로 참조하는 것은 있을 수 없는 속성 참조일 수 있습니다. postList가 Array가 아닌 object일까요?

정확한 확인을 위해 PostList 컴포넌트에서 return 에서 results 코드를 모두 제거하고, 아래의 코드로 postList 객체의 값을 화면에 그대로 찍어보면 어떤 값이 나오나요?

{JSON.stringify(postList)}

확인해보시고, 댓글 부탁드립니다.

화이팅입니다. :-)

0

똘이77

unction PostList() {
    
    const [postList, setPostList] = useState([]);
    //const headers = { Authorization: `JWT ${jwtToken}` };

    const [{data: originPostList, loading, error}, refetch] = useAxios({
        url: "/api/posts/",
        //headers
    });

    useEffect(() => {

        if (originPostList) {
            console.log("originPostList", originPostList);
            setPostList(originPostList);

        }

        console.log("mouted");


    }, [originPostList]);

    console.log("loaded respaonse2 :", postList);

    return (
        <div>

            {postList['results'] && postList['results'].length === 0 && (
                <Alert type="warning" message="포스팅이 없습니다. :-("/>
            )}
            {postList['results'] &&
                postList['results'].map(post => (
                    <Post post={post} key={post.id}/>
                ))}

        </div>
    );
}

export default PostList;

말씀하신대로 undefined 가 아닐경우만 들어가게 해서 데이터는 잘 바인딩 됩니다

그런데

loaded respaonse2 : []

PostList.js:26 mouted

PostList.js:31 loaded respaonse2 : []

PostList.js:31 loaded respaonse2 : []

PostList.js:21 originPostList {count: 2, next: null, previous: null, results: Array(2)}

PostList.js:26 mouted

PostList.js:31 loaded respaonse2 : {count: 2, next: null, previous: null, results: Array(2)}

이렇게 재랜더링이 4번이 되는데 리액트 생명주기를 제대로 짯는지 여쭤봅니다

0

이진석

위 코드 상으로는 큰 이슈가 없어보입니다. 재렌더링은 해당 컴포넌트 뿐만 아니라 부모 컴포넌트의 재렌더링 시에도 재렌더링이 발생할 수도 있습니다. 재렌더링 최적화를 처음부터 과하게 신경쓰실 필요는 없구요. 과한 최적화는 오히려 독이 됩니다.

setPostList를 통해 object, 즉 {} 값을 설정하시는 데
postList 상탯값의 초기값은 array,즉 [] 로 두셨네요. 초기값을 {} 로 두시거나
setPostList 시에 array인 results 값만 상탯값에 반영하시는 것이 보다 나은 접근일 것입니다.

화이팅입니다. :-)

0

똘이77

감사합니다!

안녕하세요.

0

62

1

[OneToOne Field Demo] get_user_model() 메서드를 활용해야 하는 이유?

0

285

1

useEffect 훅에서 else 유무에 따른 결과

0

222

1

useAxios 훅의 dependency array 설정

0

254

1

useEffect에서 변수 업데이트 관련 질문

0

389

1

rest_framework.generics.CreateAPIView의 model 속성 유무

0

276

1

bootstrap4

0

480

4

리뉴얼 강의가 오픈이 되면 기존 강의는 더이상 못보는걸까요

1

374

1

admin form에서 앞선 필드 선택 후 다른 필드 select widget 구성하는 방법

0

578

3

useState는 필수일까요?

0

272

1

python manage.py makemigrations instagram 시 created_at default 오류가 발생합니다.

0

610

4

Django allauth를 사용한 소셜 로그인 시 에러

0

660

1

프로젝트명 변경 뒤, 디버그툴바+디버그모드 사용 시 에러

0

569

2

useLocalStorage() 함수 사용여부

0

237

1

django에 LOGIN_URL = '/accounts/login/'의 의미?

0

453

1

리듀서의 의미 재확인

0

439

1

simple-jwt Refresh Token 사용 노하우

0

906

2

docker compose 를 통한 배포 관련 오류 문의

0

686

1

파이썬 속도 장고 관련 궁금한게 있습니다.

0

372

1

is_like_user

0

238

1

related_name 오류

0

278

1

re_path 오류

0

265

1

re_path url

0

255

1

No post matches the given query

0

671

2