현재 폼에는 두 가지를 설정할 수 있다.
1. 일정
2. 진행 상황
이 두 가지가 변하면 자동으로 리랜더링 되게끔
useState로 관리한다.
아래와 같이 각 각 관리도 가능하지만
이 두개는 하나의 폼에서 입력되는 값이므로
객체에 담아서 사용이 가능하다.
그리고 폼에도 input창에 값이 바뀌면 setTask로 바뀐 값이 업데이트돼서 저장되게끔 코드를 수정한다.
const handleChange = (e) => {
const { name, value } = e.target;
setTaskData((prev) => {
return { ...prev, [name]: value };
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(taskData);
};
테스트한다.
입력한 값으로 콘솔에 잘 출력되는지 테스트
현재 아래와 같이 태그가 있다.
일정 등록 시 해당 태그를 선택하면 같이 선택하여 넣을 수 있도록 한다
TaskForm에 tags를 추가한다.
여러 개가 선택될 수 있으니 배열로 하였다.
일단 태그를 선택하면 그 태그의 값을 콘솔에서 출력하는지만 테스트 해보겠다.
이제 콘솔이 아닌 setTaskData로 넣어보도록 하겠다.
그리고 이미 선택한 태그가 있으면 삭제,
선택한 태그가 없으면 추가하게끔 코드를 수정해 본다.
//선택한 태그를 tags에 추가한다( 있으면 삭제 없으면 추가)
const selectTag = (tag) => {
if (taskData.tags.some((item) => item === tag)) {
const filterTags = taskData.tags.filter((item) => item !== tag);
setTaskData((prev) => {
return { ...prev, tags: filterTags };
});
} else {
setTaskData((prev) => {
return { ...prev, tags: [...prev.tags, tag] };
});
}
};
console.log(taskData.tags); //태그 선택 확인
그리고 선택한 태그에 배경 색상을 넣어서 표시하기 위해서
checkTag 함수를 props로 넣어준다.
import "./Tag.css";
const Tag = ({ tagName, selectTag, selected }) => {
const tagStyle = {
HTML: { backgroundColor: "#fda821" },
CSS: { backgroundColor: "#15d4c8" },
JavaScript: { backgroundColor: "#ffd12c" },
REACT: { backgroundColor: "#4cdafc" },
default: { backgroundColor: "#f9f9f9" },
};
return (
<button
type="button"
className="tag"
onClick={() => selectTag(tagName)}
style={selected ? tagStyle[tagName] : tagStyle.default}
>
{tagName}
</button>
);
};
export default Tag;
Tag.jsx에서 props를 추가하고
props selected 가 true이면 위의 태그색으로 벡그라운드 색을 바꿔준다.
App.jsx에서
tasks state를 만들어준다.
TaskForm으로 setTasks 함수를 전달해서 Form에 새 taskData를 만들면
저장한다.
TaskForm 에 props로 setTasks를 받음
그리고 submit 이벤트가 일어나면
새로운 일정을 추가한다.
App.jsx에서 TaskColumn의 props에 새로 추가된 tasks와 상태를 추가한다.
TaskColum.jsx에
추가된 props를 입력한다.
그리고 tasks의 길이가 0보다 클 경우(공백이 아닐 경우)에는
map 반복문을 사용하여 배열의 길이만큼
TaskCard 컴포넌트를 사용해서 리턴한다.
0 보다 작을 경우( 공백일 경우)에는 null을 리턴한다
import TaskCard from "./TaskCard";
import "./TaskColumn.css";
export default function TaskColumn({ title, icon, tasks, status }) {
return (
<section className="task_column">
<h2 className="task_column_heading">
<img className="task_column_icon" src={icon} alt="" />
{title}
</h2>
{tasks.length > 0
? tasks.map(
(task, index) =>
task.status === status && (
<TaskCard key={index} title={task.task} tags={task.tags} />
)
)
: null}
</section>
);
}
TaskCard.jsx
import Tag from "./Tag";
import deleteIcon from "../assets/delete.png";
import "./TaskCard.css";
const TaskCard = ({ title, tags }) => {
return (
<article className="task_card">
<p className="task_text">{title}</p>
<div className="task_card_bottom_line">
<div className="task_card_tags">
{tags.map((tag, index) => (
<Tag tagName={tag} key={index} selected={true} />
))}
</div>
<div className="task_delete">
<img className="delete_icon" src={deleteIcon} alt="" />
</div>
</div>
</article>
);
};
export default TaskCard;
현재는 일정을 추가하기 눌러도 입력창의 값들이 초기화되지 않는다.
그래서 일정을 추가 한 다음 입력창이 처음처럼 초기화 하게끔 코드를 추가한다.
TaskForm.jsx
이제 휴지통 버튼을 누르면 해당 일정이 삭제되게끔 만들어 본다.
App 에 삭제하는 handleDelete 함수를 만든다.
이 함수는 인덱스번호를 입력변수로 받아서 그 인덱스 번호에 해당하는 task를 필터로 거르고(삭제하고) 다시 업데이트 하므로 해당 인덱스의 task를 삭제한다.
App .jsx에 handleDelete를 만든 이유는 모든 tasks의 state가 여기 있기 때문임
TaskColumn 컴포넌트에 handleDelete props를 내려준다.
TaskColumn.jsx 에
handleDelete props를 받고 ,
TaskCard 컴포넌트에 props로 전달한다.
그리고 map반복문의 key ={index}도 index={index}로 변경
TaskCard.jsx
휴지통 이미지에 onclick 이벤트로 handleDelete함수를 실행한다 index를 넣어 어떤 값을 삭제하는지 설정한다.
마지막으로 현재는 새로고침을 하게되면
입력했던 일정들이 다 초기화 된다.
그래서 useEffect를 사용해서 로컬스토리지에 저장하도록 하겠다.
로컬스토리지에 tasks라는 키로 값 들어가있음
saveTasks를 가져올 때 null일 경우에는 오류가 날 수 있으므로
or로 [ ] 빈 배열 만들어준다
새로고침을 해도 로컬스토리지에 저장된 값 그대로 초기화 되지 않음을 확인 가능하다.
'FRONTEND > React' 카테고리의 다른 글
[영화 앱 2] TMDB API 사용하여 영화 데이터 불러오기 (0) | 2023.11.22 |
---|---|
[task 관리 앱] css적용 / 배포하기(vite) (0) | 2023.11.21 |
[task 관리 앱] 일정 관리 앱 만들기 1 (1) | 2023.11.20 |
[이미지 갤러리] 배포하기 (API 키 ) (0) | 2023.11.20 |
[이미지 갤러리] tailwind 사용 및 Pixabay API 사용하여 검색 결과에 맞는 이미지 가져오기 (1) | 2023.11.20 |