- 메인 페이지에서 일기를 작성하면 그동안 작성한 일기 목록을 보여주는 페이지를 만들려고 한다.
- 가상으로 만들어놓은 데이터를 가지고 여러가지 가공을 하면서 초안 구현을 해봤다.
작성한 일기 데이터를 가져오는 메서드인 getDiaryList가 원래는 DiaryList 컴포넌트 안에 있었다.
DiaryList가 렌더링되면 useEffect를 통해 비동기 함수를 작동시키고 바로 button에 데이터를 가공하여 띄울 생각이였으나 useEffect로 비동기 함수가 실행되는 순서보다 렌더링되는 순서가 루프상에서는 더 빠르기 때문에 버튼에 값이 제대로 들어가지 않는 에러가 발생했다.
그래서 getDiaryList를 메인페이지로 옮기고 DiaryList는 무조건 메인페이지를 거쳐서 들어갈 수 밖에 없는 구조를 이용하여 메인페이지에서 렌더링될 때 useEffect를 통해 데이터를 가져오고 useRef로 이 값을 저장하여 렌더링으로 계속 값을 받아오는 것이 아니라 캐싱하여 자식 컴포넌트로 캐싱된 값을 전달하는 구조를 택했고, 자식 컴포넌트에서도 정상적으로 출력됐다.
app.js const Diary = () => { const [clickPage, setClickPage] = useState(false); const [diaryContent, setDiaryContent] = useState(''); const listData = useRef(); useEffect(() => { getDiaryList(); }, [listData]); async function getDiaryList() { try { const res = await axios.get('url/diarys/info'); listData.current = res.data.diaryInfoList; } catch (err) { console.log(err); } } return ( <> <Tabs tabPosition={'right'} onTabClick={onChangePage}> <TabPane tab='Calender' key='1'></TabPane> <TabPane tab='Diary List' key='2'> <DiaryList listData={listData} /> // 해당 컴포넌트에서 작업 </TabPane> <TabPane tab='Set Up' key='3'></TabPane> </Tabs> </> ); };
- 아래와 같이 map+자식 컴포넌트로 태그를 복제하는 구조에서 각 태그에 각각 접근하기 위해 배열의 index값을 custom attribute로 추가했다.
- 그래서 버튼을 클릭하면 index값과 데이터 배열을 비교하여 index가 일치하는 값을 보여주는 구조를 짰는데 useRef로는 각 태그마다 고유한 useRef를 선언해야 돼서 코드 중복이 발생했다.
- 그래서 찾은 방법이 e.target.getAttribute('name')이다.'name'에 해당하는 속성명을 변수로 지정하여 배열과 index값을 비교하기 쉬워졌고, 단 한 줄의 코드로 무한대로 원하는 값을 반환시킬 수 있게 됐다.
DiaryList.js const DiaryList = memo(({listData}) => { const {current} = listData; const sortList = [...current].reverse(); // 다이어리 리스트 최신 작성 순의 배열 useEffect(() => { console.log(`listData:${current}`); }); const onClickList = (e) => { // 각 인덱스에 맞는 값을 불러오기 첫번째칸 > 데이터 배열의 첫번째 요소 // getAttribute > 요소의 속성 직접 가져옴(custom attribute 가져올때 유용함) console.log(sortList[e.target.getAttribute('index')]); }; return ( <> <div className='diaryListContainer'> {sortList.map((v, i) => { return <MapButton className='diaryListButton' index={i} onClick={onClickList} key={v.update_time} props={v} />; })} </div> </> ); });
- 아직 부모,자식 컴포넌트간 props를 주고 받는게 많이 계속해서 찾아가면서 작성했다.
const MapButton = memo(({index, props, onClick}) => { console.log(props); return ( <button index={index} onClick={onClick}> {props.diary_reg_date.slice(0, 10)} {props.diary_weather_type} {props.diary_feel_type} </button> ); });
- 이전에 지적했던 성능 최적화
- 더 깔끔한 코드를 짤 수 있지 않을까 생각된다. 코드 가독성 올리기