• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    미해결

소스코드 링크 확인 부탁드려요.

22.05.27 23:46 작성 조회수 251

1

안녕하세요.
 
공식도큐먼트를 봐도 생소하고 어려운 개념들을 실제 코드를 통해 쉽고 친절하게 전달해주셔서 초보자입장에서 감사히 잘 보고 있습니다.
 
해당 강좌의 소소코드링크가 보이지 않는데 확인부탁드리겠습니다.
 
감사합니다.

답변 2

·

답변을 작성해보세요.

1

tkddyd420님의 프로필

tkddyd420

2022.05.28

이번 강의에서는 App.js , DiaryEditor.js , DiaryItem.js 파일만 수정하였습니다.
이번에는 전 강의에서 배운 useCallback과 React.memo를 통한 컴포넌트 렌더링 성능 최적화를 하였습니다.

 

이정환 강사님께서 보통 소스코드 올려주셨는데 여기에는 주소가 안보이네요. 제가 대신 이번 강의에서 수정한 파일 소스코드를 올리겠습니다. 혹시나 문제가 생길시 연락주시면 바로 삭제하겠습니다.

먼저 App.js 입니다.

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import './App.css';
import DiaryEditor from './DiaryEditor';
import DiaryList from './DiaryList';

function App() {
const [data, setData] = useState([]);

const dataId = useRef(0);

const getData = async () => {
const res = await fetch(
'https://jsonplaceholder.typicode.com/comments'
).then((res) => res.json());

const initData = res.slice(0, 20).map((it) => {
return {
author: it.email,
content: it.body,
emotion: Math.floor(Math.random() * 5) + 1,
created_date: new Date().getTime(),
id: dataId.current++,
};
});
setData(initData);
};

useEffect(() => {
getData();
}, []);

const onCreate = useCallback((author, content, emotion) => {
const created_date = new Date().getTime();
const newItem = {
author,
content,
emotion,
created_date,
id: dataId.current,
};
dataId.current += 1;
setData((data) => [newItem, ...data]);
}, []);

const onRemove = useCallback((targetId) => {
setData((data) => data.filter((it) => it.id !== targetId));
}, []);

const onEdit = useCallback((targetId, newContent) => {
setData((data) =>
data.map((it) =>
it.id === targetId ? { ...it, content: newContent } : it
)
);
}, []);

const getDiaryAnalysis = useMemo(() => {
const goodCount = data.filter((it) => it.emotion >= 3).length;
const badCount = data.length - goodCount;
const goodRatio = (goodCount / data.length) * 100;
return { goodCount, badCount, goodRatio };
}, [data.length]);

const { goodCount, badCount, goodRatio } = getDiaryAnalysis;

return (
<div className="App">
<DiaryEditor onCreate={onCreate} />
<div>전체 일기 : {data.length}</div>
<div>기분 좋은 일기 개수 : {goodCount}</div>
<div>기분 나쁜 일기 개수 : {badCount}</div>
<div>기분 좋은 일기 비율 : {goodRatio}</div>
<DiaryList onEdit={onEdit} onRemove={onRemove} diaryList={data} />
</div>
);
}

export default App;

DiaryEditor.js 입니다.

import React, { useRef, useState } from 'react';

const DiaryEditor = ({ onCreate }) => {
const authorInput = useRef();
const contentInput = useRef();
const [state, setState] = useState({
author: '',
content: '',
emotion: 1,
});

const handleChangeState = (e) => {
setState({
...state,
[e.target.name]: e.target.value,
});
};

const handleSubmit = () => {
if (state.author.length < 1) {
authorInput.current.focus();
return;
}

if (state.content.length < 5) {
contentInput.current.focus();
return;
}

onCreate(state.author, state.content, state.emotion);
alert('저장 성공!');
setState({
author: '',
content: '',
emotion: 1,
});
};

return (
<div className="DiaryEditor">
<h2>오늘의 일기</h2>
<div>
<input
ref={authorInput}
value={state.author}
onChange={handleChangeState}
name="author"
placeholder="작성자"
type="text"
/>
</div>
<div>
<textarea
ref={contentInput}
value={state.content}
onChange={handleChangeState}
name="content"
placeholder="일기"
type="text"
/>
</div>
<div>
<span>오늘의 감정점수 : </span>
<select
name="emotion"
value={state.emotion}
onChange={handleChangeState}
>
<option value={1}>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
<option value={5}>5</option>
</select>
</div>
<div>
<button onClick={handleSubmit}>일기 저장하기</button>
</div>
</div>
);
};
export default React.memo(DiaryEditor);

 DiaryItem.js  입니다.

import React, { useEffect, useRef, useState } from 'react';

const DiaryItem = ({
onEdit,
onRemove,
id,
author,
content,
emotion,
created_date,
}) => {
useEffect(() => {
console.log(`${id}번 째 아이템 렌더!`);
});
const [isEdit, setIsEdit] = useState(false);
const toggleIsEdit = () => setIsEdit(!isEdit);

const [localContent, setLocalContent] = useState(content);
const localContentInput = useRef();

const handleRemove = () => {
if (window.confirm(`${id}번째 일기를 정말 삭제하시겠습니까?`)) {
onRemove(id);
}
};

const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
};

const handleEdit = () => {
if (localContent.length < 5) {
localContentInput.current.focus();
return;
}

if (window.confirm(`${id}번 째 일기를 수정하시겠습니까?`)) {
onEdit(id, localContent);
toggleIsEdit();
}
};

return (
<div className="DiaryItem">
<div className="info">
<span>
작성자 : {author} | 감정점수 : {emotion}
</span>
<br />
<span className="date">{new Date(created_date).toLocaleString()}</span>
</div>
<div className="content">
{isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) => setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
</div>

{isEdit ? (
<>
<button onClick={handleQuitEdit}>수정 취소</button>
<button onClick={handleEdit}>수정 완료</button>
</>
) : (
<>
<button onClick={handleRemove}>삭제하기</button>
<button onClick={toggleIsEdit}>수정하기</button>
</>
)}
</div>
);
};

export default React.memo(DiaryItem);

0

@tkddyd420

코드전체를 작성해주셨군요. 감사합니다!