

react TO-DO-LIST 사용자가 할 일 목록을 관리할 수 있는 웹 애플리케이션입니다.
구현기능
- TODOLIST 구현
- TODO 필터링 구현
- TODO 완료/미완료 표시
- TODO 레이아웃 전환 CSS
props
todos, workState, toggles는 리덕스로 받아온 값이다.
- todos : todolist의 content를 받아온다.
- workState : todo의 완료 미완료 필더값을 받아온다.
- toggle : todo의 레이아웃값을 받아온다.
함수
- getKeyByValue는 객체로 담겨있는 toggles의 값을 받아온다.
- isdoneColor todo의 완료 미완료 상태(isdone)에 따라 스타일 컴포넌트로 넣어줄 컬러를 반환한다.
- todoList는 workState의 값에 따라 완료/ 미완료/ 전체를 나눠 필터링해 배열을 반환한다.
function TodoListItem({ todos, workState, toggles }) {
const dispatch = useDispatch();
const getKeyByValue = () => {
for (let key in toggles) {
if (toggles[key] && key) {
return key;
}
}
};
const isdoneColor = (isdone) => {
return isdone === true ? '#31af7f' : '#b5b5b5';
};
console.log(getKeyByValue());
const todoList = () => {
if (workState === 'all') {
return todos;
} else {
return todos.filter((item) => item.isDone === workState);
}
};
return (
<TodoItemBlock>
{todoList().map((item, idx) => {
return (
<TodoItem
key={item.id}
className={getKeyByValue()}
isdonecolor={item.isDone ? `#e1fff6` : '#fff'}
>
<IdBox className={getKeyByValue()}>{idx + 1}</IdBox>
<StyledContent item={item} getKeyByvalue={getKeyByValue()} />
<IconBox className={getKeyByValue()} isdonecolor={isdoneColor(item.isDone)}>
<Check
id="check-icon"
onClick={() => {
dispatch(toggleItem(item.id));
}}
/>
<Delete
id="delete-icon"
onClick={() => {
dispatch(deleteItem(item.id));
}}
/>
</IconBox>
</TodoItem>
);
})}
</TodoItemBlock>
);
}
스타일 컴포넌트 (스타일링 부분은 제거)
const StyledfilterBlock = styled.div` . . . display: flex; position: relative; transition: all 0.3s ease-in-out; label { . . . z-index: 99; position: relative; display: flex; align-items: center; justify-content: space-around; cursor: pointer; &.active { color: #31be86; .countNum { background-color: #fff; } } } `; const Glider = styled.span` . . . position: absolute; z-index: 1; transition: 0.25s ease-out; transform: translateX(${(props) => props.translatevalue}%); `; const CountNum = styled.span` display: inline-block; . . . `;
filter bar 컴포넌트
useState를 사용하지 않으면 리렌더링이 안되기 때문에 사용했다.
- Span : 스타일 컴포넌트로 translate에 props 값을 전달
- active : label의 active 클래스 추가 제거
- onChangeHandler : workState로 값을 전달
const Styledfilter = ({ onChangeHandler, workNum, doneNum }) => { const [span, setSpan] = useState(0); const [active, setActive] = useState(1); const tabMove = (x, id, value) => { setSpan(x); setActive(id); onChangeHandler(value); }; return ( <StyledfilterBlock> <Glider translatevalue={span}></Glider> <label onClick={() => tabMove(0, 1, 'all')} className={active === 1 ? 'active' : ''}> All </label> <label onClick={() => tabMove(100, 2, 'working')} className={active === 2 ? 'active' : ''} 🔥 Working..! <CountNum className="countNum">{workNum}</CountNum> </label> <label onClick={() => tabMove(200, 3, 'done')} className={active === 3 ? 'active' : ''}> 🌈 Done...! <CountNum className="countNum">{doneNum}</CountNum> </label> </StyledfilterBlock> ); };


UI 컴포넌트 재사용
input, textarea, button 컴포넌트를 재사용했다.
const TodoUpdate = ({ todo }) => {
return (
<TodoUpdateBlock>
<UpdatePage>
<Link to="/">
<BackButton backgroundcolor={`#31be86`} hovercolor={`#c9f4e9`}></BackButton>
</Link>
<form>
<StyledInput value={'리액트 공부하기'} height={`40px`} radius={`14px`} />
<StyledTextArea value={'리액트 공부하기'} />
<StyledButton buttontext={'update'} />
</form>
</UpdatePage>
</TodoUpdateBlock>
);
};
const BackBtn = styled.button`
width: 143px;
height: 36px;
border: none;
background-color: ${(props) => props.backgroundcolor || `#c9f4e9`};
color: ${(props) => props.hovercolor || `#31be86`};
.
.
.
&:hover {
background-color: ${(props) => props.hovercolor || `#31be86`};
color: ${(props) => props.backgroundcolor || `#fff`};
}
`;
const BackButton = ({ backgroundcolor, hovercolor }) => {
return (
<BackBtn backgroundcolor={backgroundcolor} hovercolor={hovercolor}>
<FontAwesomeIcon icon={faReply} id="icon-reply" />
이전
</BackBtn>
);
};
export default BackButton;