일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 좌우슬라이드
- 자바스크립트
- 티스토리 #폰트변경 #꾸미기
- 숫자게임만들기
- array #object #lodash #javascript
- 파비콘 #파비콘만들기 #포토샵파비콘
- React
- 가장작은자연수
- darkmode
- GIT
- 음악검색기능 #음악찾기기능 #음악찾기 #음악검색 #네이버음악검색 #다음음악검색 #멜론음악검색
- fadeint
- fade-in
- 요일구하는공식
- 자바스크립트 #메뉴만들기
- 메뉴
- 윈도우10캡쳐 #윈도우10캡처 #윈도우10스크린샷 #캡쳐하기 #캡처하기 #스크린샷찍기 #캡쳐지연 #스크린샷지연
- ThemeProvider
- 슬라이드다운
- 오류
- 리액트
- list추가하기
- 요일구하기
- 문자열다루기
- 네트워크 #5G안터질때 #4G로바꾸는법 #5G를4G로 #5G를LTE로 #갤럭시5G변경
- hover효과
- todolist
- 프로그래머스
- 동영상다운 #영상다운 #크롬웹스토어 #드래그되지않는 #클릭되지않는 #동영상
- 카카오톡알림설정 #카톡알림설정
- Today
- Total
잿꽃's posting Garden
REACT Todolist 만들기 - 2 본문
REACT에서 Todolist를 만들어봤습니다.
2022.04.28 - [WEB] - REACT Todolist 만들기 - 1
REACT Todolist 만들기 - 1
REACT에서 Todolist를 만들어봤습니다. 1. UI틀 만들기 2. styled-components로 꾸미고 간단한 속성 부여하기 3장. 멋진 투두리스트 만들기 · GitBook (vlpt.us) 3장. 멋진 투두리스트 만들기 · GitBook 3장. 멋..
flowerofashes.tistory.com
3. 기능 구현하기
마침 강의 평가가 있어서 강의에서 배운 내용을 토대로 기능을 구현해 보았습니다.
1. app.js와 TodoListTotal.js의 할 일을 수정하기
기존에 TodoListTotal.js에 직접 입력했던 내용을 상태관리가 가능하게 하기 위한 목적
- app.js내에서 할 일을 작성해주고 상태관리가 가능한 useState()를 활용한다.
- TodoListTotal의 속성 값으로 useState()의 기본 상태인 todoList를 전달한다.
/////////////////app.js/////////////////
import React, {useRef, useState, useCallback} from 'react';
import TodoListHeader from './Components/TodoListHeader';
import TodoListWrap from './Components/TodoListWrap';
import TodoListTotal from './Components/TodoListTotal';
import TodoListAdd from './Components/TodoListAdd';
const App = () => {
// todolist의 내용 기본 셋팅
const [todoList, setTodoList] = useState([
{ id: 1, text: 'UI 구성 생각하기', check : true},
{ id: 2, text: '각각의 Components 만들기', check : true},
{ id: 3, text: 'Styled-Components로 꾸미기', check : true},
{ id: 4, text: '기능 구현하기', check : false},
]);
return (
<div>
<TodoListWrap>
<TodoListHeader></TodoListHeader>
<TodoListTotal todoList={todoList}></TodoListTotal>
<TodoListAdd></TodoListAdd>
</TodoListWrap>
</div>
);
};
export default App;
- TodoListTotal.js에서 전달받은 todoList를 map함수를 통해 TodoListItem 컴포넌트에 그대로 전달하고 key값을 id값으로 이용한다.
////////////////////TodoListTotal.js////////////////////
import React from 'react';
import styled from 'styled-components';
import TodoListItem from './TodoListItem';
// 전체 할 일을 감싸는 용도
// app.js에서 받은 속성을 TodoListItem에 그대로 전달한다.
const TodoListTotal = ({todoList}) => {
return (
<TodoTotal>
{todoList.map(todo=>(<TodoListItem todo={todo} key={todo.id}></TodoListItem>))}
</TodoTotal>
);
};
const TodoTotal = styled.div`
display: flex;
flex: 1;
flex-direction: column;
margin-top: 10px;
`;
export default TodoListTotal;
2. TodoListHeader.js에서 남은 할 일의 개수 세기
app.js에서 작성된 list중에서 check가 false인 값을 세기 위한 목적
- app.js에서 TodoListHeader.js로 todoList를 전달한다.
/////////////////app.js/////////////////
import React, {useRef, useState, useCallback} from 'react';
import TodoListHeader from './Components/TodoListHeader';
import TodoListWrap from './Components/TodoListWrap';
import TodoListTotal from './Components/TodoListTotal';
import TodoListAdd from './Components/TodoListAdd';
const App = () => {
// todolist의 내용 기본 셋팅
const [todoList, setTodoList] = useState([
{ id: 1, text: 'UI 구성 생각하기', check : true},
{ id: 2, text: '각각의 Components 만들기', check : true},
{ id: 3, text: 'Styled-Components로 꾸미기', check : true},
{ id: 4, text: '기능 구현하기', check : false},
]);
return (
<div>
<TodoListWrap>
<TodoListHeader todoList={todoList}></TodoListHeader>
<TodoListTotal todoList={todoList}></TodoListTotal>
<TodoListAdd></TodoListAdd>
</TodoListWrap>
</div>
);
};
export default App;
- 전달 받은 todoList를 filter()함수를 통해 전달받은 list중에서 check의 값이 false인 값만 변수에 담는다.
const nonCheck = todoList.filter(todo => !todo.check)라고도 쓸 수 있다. true인 값만 반환되기 때문이다.
- p태그에 필터로 걸러진 배열의 길이를 입력한다.
/////////////////TodoListHeader.js/////////////////
import React, {useEffect, useState} from 'react';
import styled from 'styled-components';
// 오늘의 날짜와 남은 할일을 보여주는 용도
const TodoListHeader = ({todoList}) => {
// todoList에서 각 요소의 check가 true가 아닌 것만 반환한다.
const nonCheck = todoList.filter(todo=> todo.check !== true)
// 시간의 상태 변화를 렌더링 할 useState
const [time, setTime] = useState(new Date())
// 문서가 마운트 되었을 때 실행된다.
// setInterval함수로 1초마다 새로운 시간을 받는다.
useEffect(()=>{
setInterval(()=>{
setTime(new Date())
},1000)
},[])
return (
<TodoHeader>
<h1>{time.toLocaleDateString()}</h1>
<p>할일이 {nonCheck.length}개 남았습니다.</p>
</TodoHeader>
);
};
const TodoHeader = styled.div`
width: 100%;
padding: 20px;
border-bottom: 1px solid #ccc;
h1{
margin-top: 10px;
}
p{
margin-top: 1rem;
color: #219ebc;
}
`;
export default TodoListHeader;
3. 새로운 할 일 기능을 추가하기
input에서 입력된 내용을 새 배열에 저장하고 기존 배열과 합치기 위한 목적
- 업데이트 되어도 값이 변하지 않으면서 화면에 변화된 값이 나타나지 않아도 되는 id값을 useRef()를 활용하여 다음 id값을 생성
- 리스트를 추가할 때 todoList에 관련해서 렌더링될 때만 작업이 수행되도록 useCallback()을 사용.
texts에는 TodoListAdd.js에서 input값으로 전달받은 값이 들어갈 예정
- setTodoList에 기존의 list에 concat()을 활용하여 추가할 list를 합친다.
- useRef()의 현재 값을 1증가시킨다( nextId.current++과 동일 )
- 만든 변수를 TodoListAdd.js로 속성 값으로 전달.
/////////////////app.js/////////////////
import React, {useRef, useState, useCallback} from 'react';
import TodoListHeader from './Components/TodoListHeader';
import TodoListWrap from './Components/TodoListWrap';
import TodoListTotal from './Components/TodoListTotal';
import TodoListAdd from './Components/TodoListAdd';
const App = () => {
// todolist의 내용 기본 셋팅
const [todoList, setTodoList] = useState([
{ id: 1, text: 'UI 구성 생각하기', check : true},
{ id: 2, text: '각각의 Components 만들기', check : true},
{ id: 3, text: 'Styled-Components로 꾸미기', check : true},
{ id: 4, text: '기능 구현하기', check : false},
]);
// 다음 id값을 지정하기 위함
const nextId = useRef(5)
// 새로운 할 일 추가 기능
// useCallback을 이용하여 todolist에 관해서만 렌더링
// 새로운 list를 만들어(newList) 기존 리스트(setTodoList)와 합친다.
const addList = useCallback(texts =>{
const newList = {
id : nextId.current,
text : texts,
check : false
}
setTodoList(todoList.concat(newList))
nextId.current+= 1
}, [todoList])
return (
<div>
<TodoListWrap>
<TodoListHeader todoList={todoList}></TodoListHeader>
<TodoListTotal todoList={todoList}></TodoListTotal>
<TodoListAdd addList={addList}></TodoListAdd>
</TodoListWrap>
</div>
);
};
export default App;
- TodoListAdd.js 전달 된 addList를 인자에 입력
- addList함수를 이용하기 전 input을 감지할 내용이 필요할 것이다.
- useState()를 활용하여 input의 기본 value의 값을 지정함. inputText가 input의 value값을 가지고 있으므로 '할 일을 입력해보세요'라는 문구를 입력해도 좋을 듯하다.
- setInputText에 해당하는 value의 값을 넣는다.
- input에 onChange이벤트와 value의 값에 해당하는 내용을 각각 넣어준다.
- app.js에서 가져온 addList에 인자 texts에 값을 넣어야 하는데 이 부분은 'text : '에 해당하므로 inputText를 넣어준다. 추가 후 input상자에 value값이 남아있으면 안 되므로 setInputText를 이용해 초기화한다.
- input상자에 onSubmit이벤트에 만든 함수를 추가한다.
* onSubmit 이벤트를 이용하기 위해서는 해당 박스의 속성이 form의 요소이어야 한다. styled-components에서 지정한 div를 form으로 수정하였다. (const TodoAdd = styled.form` css 내용 `;)
/////////////////TodoListAdd.js/////////////////
import React, {useCallback, useState} from 'react';
import styled from 'styled-components';
import {IoMdAddCircle} from 'react-icons/io';
import {css} from 'styled-components'
// 할 일을 추가하는 용도
const TodoListAdd = ({addList}) => {
// 추가 버튼에 따라 입력창이 열리고 닫히는 효과
const [open, setOpen] = useState(false);
const [inputText, setInputText] = useState('');
// 입력한 값을 감지하는 함수
const onChange = useCallback((e)=>{
setInputText(e.target.value)
},[])
// 감지한 내용을 리스트에 추가하는 함수
const onSubmit = useCallback((e)=>{
addList(inputText)
setInputText('')
e.preventDefault()
},[addList, inputText])
return (
<TodoAdd onSubmit={onSubmit}>
{ open && <InputBox>
<input type="text" onChange={onChange} value={inputText}></input>
</InputBox>}
<TodoAddBtn onClick={()=>setOpen(!open)} open={open}></TodoAddBtn>
</TodoAdd>
);
};
const TodoAdd = styled.form`
width: 100%;
height: 120px;
position: relative;
`;
const InputBox =styled.div`
width: 100%;
height: 120px;
background: #ccc;
text-align: center;
input{
width: 60%;
height: 30px;
margin-top: 15px;
}
`;
const TodoAddBtn = styled(IoMdAddCircle)`
position: absolute;
left: 0;
right: 0;
margin: 0 auto;
bottom: 5px;
font-size: 4rem;
color: #219ebc;
cursor: pointer;
&:hover{
color: #63e6be;
}
${(props)=> props.open &&
css`
&:hover{
color: #ff8787;
}
color: #ff8787;
transform: rotate(45deg)
`}
`;
export default TodoListAdd;
4. 할 일을 삭제하는 기능 구현하기
list에서 선택한 요소가 리스트 중에 일치하는 것을 거르는 목적
- filter()를 이용해 선택한 아이디가 기존의 아이디와 일치하지 않는 것만 setTodoList에 담는다.
- 만든 변수를 TodoListTotal.js에 전달. 이 동작은 TodoListTotal.js이 아닌 TodoListItem.js에서 실행되어야 하므로 중간 전달 역할을 한다.
/////////////////app.js/////////////////
import React, {useRef, useState, useCallback} from 'react';
import TodoListHeader from './Components/TodoListHeader';
import TodoListWrap from './Components/TodoListWrap';
import TodoListTotal from './Components/TodoListTotal';
import TodoListAdd from './Components/TodoListAdd';
const App = () => {
// todolist의 내용 기본 셋팅
const [todoList, setTodoList] = useState([
{ id: 1, text: 'UI 구성 생각하기', check : true},
{ id: 2, text: '각각의 Components 만들기', check : true},
{ id: 3, text: 'Styled-Components로 꾸미기', check : true},
{ id: 4, text: '기능 구현하기', check : false},
]);
// 다음 id값을 지정하기 위함
const nextId = useRef(5)
// 새로운 할 일 추가 기능
// useCallback을 이용하여 todolist에 관해서만 렌더링
// 새로운 list를 만들어(newList) 기존 리스트(setTodoList)와 합친다.
const addList = useCallback(texts =>{
const newList = {
id : nextId.current,
text : texts,
check : false
}
setTodoList(todoList.concat(newList))
nextId.current++
}, [todoList])
// 할일 삭제하는 기능
// setTodoList에 todoList중 현재 id와 요소의 id가 같은지 각각 확인 후 같지 않은 것만 들어간다.
const onRemove = useCallback(id => {
setTodoList(todoList.filter((todo) => todo.id !== id))
},[todoList]
);
return (
<div>
<TodoListWrap>
<TodoListHeader todoList={todoList}></TodoListHeader>
<TodoListTotal todoList={todoList} onRemove={onRemove}></TodoListTotal>
<TodoListAdd addList={addList}></TodoListAdd>
</TodoListWrap>
</div>
);
};
export default App;
- TodoListTotal.js에서 TodoListItem.js로 전달한다.
/////////////////TodoListTotal.js/////////////////
import React from 'react';
import styled from 'styled-components';
import TodoListItem from './TodoListItem';
// 전체 할 일을 감싸는 용도
// app.js에서 받은 속성을 TodoListItem에 그대로 전달한다.
const TodoListTotal = ({todoList, onRemove}) => {
return (
<TodoTotal>
{todoList.map(todo=>(<TodoListItem todo={todo} key={todo.id} onRemove={onRemove}></TodoListItem>))}
</TodoTotal>
);
};
const TodoTotal = styled.div`
display: flex;
flex: 1;
flex-direction: column;
margin-top: 10px;
`;
export default TodoListTotal;
- 전달받은 onRemove는 버리는 아이콘을 눌렀을 때 실행되어야 하므로 onClick이벤트에 넣어주고 인자는 비구조할당으로 꺼내온 id를 입력한다.
/////////////////TodoListItem.js/////////////////
import React from 'react';
import { BsCircle, BsCheckCircle, BsDashCircleFill } from 'react-icons/bs'
import styled from 'styled-components';
import {css} from 'styled-components'
// 낱개의 할 일을 나타내는 용도
// app.js > TodoListTotal.js에서 전달받은 인자를 이용한다.
const TodoListItem = ({todo, onRemove}) => {
// todo의 key값을 비구조할당으로 꺼내서 이용한다.
const {id, text, check} = todo;
return (
<TodoItem>
{ check ? <CheckBtn}></CheckBtn> : <CircleBtn}></CircleBtn>}
<TodoText check={check}>{text}</TodoText>
<RemoveBtn onClick={() => onRemove(id)}>버리기</RemoveBtn>
</TodoItem>
);
};
const CheckBtn = styled(BsCheckCircle)`
font-size: 1.5rem;
color: #219ebc;
cursor: pointer;
`;
const CircleBtn = styled(BsCircle)`
font-size: 1.5rem;
color: #888;
cursor: pointer;
`;
const RemoveBtn = styled(BsDashCircleFill)`
font-size: 1.5rem;
color: #ff8787;
display: none;
cursor: pointer;
`;
const TodoItem = styled.div`
width: 100%;
padding: 10px 20px;
display: flex;
align-items: center;
&:hover {
background: #ddd;
${RemoveBtn}{
display: initial;
}
}
`;
const TodoText = styled.div`
flex: 1;
padding-left: 10px;
color: #333;
${props=> props.check &&
css`
color: #888;
text-decoration: line-through;
`}
`;
export default TodoListItem;
5. 체크 아이콘을 누르면 아이콘이 바뀌는 기능 구현하기
list에서 선택한 요소가 리스트와 일치하는지 확인하고 일치하는 요소의 check 상태를 변경시키는 목적
- map()
2022.04.28 - [WEB] - REACT Todolist 만들기 - 1
를 이용해 모든 값을 return하지만 그중에 일치하는 요소만 check의 상태를 !를 사용해 변경(check가 아닌 key, value값은 전개연산자로 그대로 전달)
- 4번의 내용과 동일하게 TodoListTotal 컴포넌트에 전달하고 이것은 TodoListItem까지 전달할 수 있게 한다.
/////////////////app.js/////////////////
import React, {useRef, useState, useCallback} from 'react';
import TodoListHeader from './Components/TodoListHeader';
import TodoListWrap from './Components/TodoListWrap';
import TodoListTotal from './Components/TodoListTotal';
import TodoListAdd from './Components/TodoListAdd';
const App = () => {
// todolist의 내용 기본 셋팅
const [todoList, setTodoList] = useState([
{ id: 1, text: 'UI 구성 생각하기', check : true},
{ id: 2, text: '각각의 Components 만들기', check : true},
{ id: 3, text: 'Styled-Components로 꾸미기', check : true},
{ id: 4, text: '기능 구현하기', check : false},
]);
// 다음 id값을 지정하기 위함
const nextId = useRef(5)
// 새로운 할 일 추가 기능
// useCallback을 이용하여 todolist에 관해서만 렌더링
// 새로운 list를 만들어(newList) 기존 리스트(setTodoList)와 합친다.
const addList = useCallback(texts =>{
const newList = {
id : nextId.current,
text : texts,
check : false
}
setTodoList(todoList.concat(newList))
nextId.current++
}, [todoList])
// 할일 삭제하는 기능
// setTodoList에 todoList중 현재 id와 요소의 id가 같은지 각각 확인 후 같지 않은 것만 들어간다.
const onRemove = useCallback(id => {
setTodoList(todoList.filter((todo) => todo.id !== id))
},[todoList]
);
// 체크 버튼 토글의 기능
// 현재의 id와 요소의 id가 같은지 각각 확인후 같으면 check를 제외한 모든 요소는 동일하게 사용하고 check는 기존의 상태의 반대가 되게 한다. id가 다르면 동일 값을 사용한다.
const onToggle = useCallback(id => {
setTodoList(todoList.map(todo => todo.id === id ? {...todo, check : !todo.check} : todo))
},[todoList])
return (
<div>
<TodoListWrap>
<TodoListHeader todoList={todoList}></TodoListHeader>
<TodoListTotal todoList={todoList} onRemove={onRemove} onToggle={onToggle}></TodoListTotal>
<TodoListAdd addList={addList}></TodoListAdd>
</TodoListWrap>
</div>
);
};
export default App;
- TodoListTotal.js에서 TodoListItem.js로 전달한다.
/////////////////TodoListTotal.js/////////////////
import React from 'react';
import styled from 'styled-components';
import TodoListItem from './TodoListItem';
// 전체 할 일을 감싸는 용도
// app.js에서 받은 속성을 TodoListItem에 그대로 전달한다.
const TodoListTotal = ({todoList, onRemove, onToggle}) => {
return (
<TodoTotal>
{todoList.map(todo=>(<TodoListItem todo={todo} key={todo.id} onRemove={onRemove} onToggle={onToggle}></TodoListItem>))}
</TodoTotal>
);
};
const TodoTotal = styled.div`
display: flex;
flex: 1;
flex-direction: column;
margin-top: 10px;
`;
export default TodoListTotal;
- 아이콘을 누르면 check의 상태가 바뀌어야 하니 onClick이벤트에 작성하고 인자 값으로는 todo에서 꺼낸 id를 사용한다(4번과 동일 내용)
/////////////////TodoListItem.js/////////////////
import React from 'react';
import { BsCircle, BsCheckCircle, BsDashCircleFill } from 'react-icons/bs'
import styled from 'styled-components';
import {css} from 'styled-components'
// 낱개의 할 일을 나타내는 용도
// app.js > TodoListTotal.js에서 전달받은 인자를 이용한다.
const TodoListItem = ({todo, onRemove, onToggle}) => {
// todo의 key값을 비구조할당으로 꺼내서 이용한다.
const {id, text, check} = todo;
return (
<TodoItem>
{ check ? <CheckBtn onClick={()=>onToggle(id)}></CheckBtn> : <CircleBtn onClick={()=>onToggle(id)}></CircleBtn>}
<TodoText check={check}>{text}</TodoText>
<RemoveBtn onClick={() => onRemove(id)}>버리기</RemoveBtn>
</TodoItem>
);
};
const CheckBtn = styled(BsCheckCircle)`
font-size: 1.5rem;
color: #219ebc;
cursor: pointer;
`;
const CircleBtn = styled(BsCircle)`
font-size: 1.5rem;
color: #888;
cursor: pointer;
`;
const RemoveBtn = styled(BsDashCircleFill)`
font-size: 1.5rem;
color: #ff8787;
display: none;
cursor: pointer;
`;
const TodoItem = styled.div`
width: 100%;
padding: 10px 20px;
display: flex;
align-items: center;
&:hover {
background: #ddd;
${RemoveBtn}{
display: initial;
}
}
`;
const TodoText = styled.div`
flex: 1;
padding-left: 10px;
color: #333;
${props=> props.check &&
css`
color: #888;
text-decoration: line-through;
`}
`;
export default TodoListItem;
완성
완성된 내용은 아래의 사이트에서 확인이 가능합니다.
React App (ssoa1111.github.io)
React App
ssoa1111.github.io
'WEB > REACT' 카테고리의 다른 글
REACT 실수1 : styled-component에 불리안 prop가 전달이 안되는 문제 (0) | 2022.05.30 |
---|---|
REACT Todolist 만들기 - 1 (0) | 2022.04.28 |
REACT styled-components 'ThemeProvider'를 이용한 darkmode만들기 (0) | 2022.04.25 |
REACT useContext을 이용한 darkmode 만들기 (0) | 2022.04.24 |
REACT HOOK의 용도 정리 (0) | 2022.04.23 |