Client/ReactJS & React-Native

React)DB에서 가져온 정보 렌더링하기. useState 비동기화 문제.

Juzdalua 2022. 1. 24. 10:37

리듀서를 사용해 DB에서 테이블 정보를 가져왔다.

해당 정보들을 useState 훅을 사용해 state에 저장했는데,

내 state는 비어있었다.

비동기 작업으로 이루어지는 setState라서 한박자 느리게 적용된다고 한다. 

 

useEffect 훅을 함께 사용해야한다고 하는데,

나는 멍청하게 setState를 디펜던시 인자로 사용하고 있었다.

useEffect(()=>{
	getAllMemo()
},[])

useEffect(()=>{
	getAllMemo()
},[getAllMemo])

useEffect(()=>{
	getAllMemo()
},[setMemo])

useEffect를 공부하며 깨달은 사실.

1. 디펜던시 인자를 빈 배열로 설정하면, 처음 렌더링 될 때만 작동한다.

2. 디펜던시 인자를 작성하면 해당 함수나 변수가 변경할 때만 작동하는게 아니라, 

1번처럼 처음 렌더링 될 때에도 한번 작동한다. 즉, 최소 2번은 작동한다.


열심히 구글링 해본 결과, setState에서 콜백함수를 사용하면 동기화작업이 된다고 한다.

그렇게 아래와 같은 작업들을 거쳤지만, 변경되는점은 없었다.

여전히 비동기화 상태..

setMemo(response.data.data)
setMemo(() => response.data.data)
setMemo((currentArr) => [response.data.data, ...currentArr])

 

그래서 새로운 컴포넌트도 만들어보고, loading이라는 state도 만들어봤지만

여전히 문제는 해결되지 않았다.

 

그러다 stackoverflow에 한 중국인 고수가 답변을 달아줬다.

친절히 리액트 doc url도 첨부해줘서 읽어봤지만, 이전에 찾아본 구글링과 다르진 않았다.

정말 친절하게도, 이렇게 바꾸라는 코멘트도 남겨줬기에 일부를 수정하고 적용했더니...

왜 되는지 모르겠다.

내 황금같은 주말 내내 쏟아부었는데

 

 

완성된 코드를 살펴보자.

(아직도 왜 됐는지는 잘 모르겠다.)

import { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { getItem } from "../../utility/localStorage";
import { getMemoWithUser } from "../../redux/memo/actionCreator";
import "./styles.css";

const MemoList = () => {
    const [memo, setMemo] = useState([]);       
    const dispatch = useDispatch();
           
    useEffect( () => {  
        getAllMemo();
    },[]);

    let response;        
    const getAllMemo = async () => {
        // get memo list with user
        const body = {
            user_id : getItem('user').id
        };        
        response = await dispatch(getMemoWithUser(body));        
        console.log(response.data.data);
        // setMemo(prevState => ([...prevState, response.data.data]));
        setMemo( () => response.data.data)
        
    };

    useEffect(() => {        
        // todo for memo change.                    
        if(memo.length>0){
            console.log(memo);   
        }
    }, [memo]);

    return (        
        <div className="memo-container">                        
            {memo.length>0 ? memo.map( (memo, idx) => {
                return (
                    <div key={idx} className="memo-container__item">
                        <div className="memo-container__time">
                            <span>{memo.createdAt.substr(0,10)} {memo.createdAt.substr(11,5)}</span>
                        </div>
                        <div className="memo-container__memo">
                            <span>{memo.memo}</span>
                        </div>
                    </div>
                )}) 
            : <span>Loading...</span>
            }            
        </div>  
    );
};



export default MemoList;

처음에는 이렇게 코드를 수정하고도 html section에 아무 표시도 되지 않았다.

아마 map 함수를 잘못 사용했을 수도, {}의 위치가 잘못됐을수도 있다.

그래도 현재는 문제없이 잘 출력된다.