2022-03-04 01:33
스터디 프로젝트 첫 번째, 병합 전 정리...
- 디렉토리 -
1. pages
- 페이지 단위로 관리하는 디렉토리
pages/todoRoom
todoRoom 경로로 들어가면 보여지는 페이지
2. src/features
스타일-컴포넌트들 기능단위로 관리하는 디렉토리.
src/features/todoRoom
todoRoom 관련 컴포넌트들을 보관하는 디렉토리
- box 디렉토리 : pages/todoRoom 페이지에서 보여지는 todo박스, doing박스, done박스들을 보관한다.
pages/todoRoom 안에서 렌더링된다. - todoCard 디렉토리 : todoCard들을 관리하는 디렉토리이다.
src/features/todoRoom/box 안의 3개의 박스 안에서 각각 렌더링 된다. - todoRoomForm.tsx : todoCard를 생성하는 입력 양식 컴포넌트이다.
3. src/redux
리덕스 관련 파일들을 관리하는 디렉토리.
src/redux/todoRoom
todoRoom 안에서 사용할 todo 관리 리덕스.
- Todo, Doing, Done 세 개의 리듀서 각각 만들어서 관리했다.
- initState.ts : Todo, Doing, Done 세 개의 리듀서에서 사용할 초기 state 상태를 저장한다.
- 리덕스 -
'''src/redux/todoRoom/Todos'''
import { nanoid } from '@reduxjs/toolkit';
const initState:TodoType[]= [
]
interface TodoType {
id: string
title: string
manager: string
content: string
deadline: Date
createDate:Date
dueDate: Date
}
export default initState;
todoRoom 안의 todo 리덕스들에서 사용할 todo 단위 타입. 초기 상태는 빈 배열로 설정했다.
''' src/redux/todoRoom/todo'''
const TodoSlice=createSlice({
name: 'todo',
initialState:initState,
reducers: {
addTodo: {
reducer: (state, action: PayloadAction) => {
state.push(action.payload)
},
},
removeTodo: {
reducer: (state, action) => {
return state.filter(one => one.id !== action.payload)
}
},
}
});
todo, Doing, Done 세 개의 리덕스를 리덕스 toolkit의 슬라이스 기능을 이용해 생성하고, 세 개의 리듀서에 addTodo, removeTodo 액션을 만들어서 todo단위로 저장, 삭제한다.
- 컴포넌트 -
Box 컴포넌트들
'''src/features/todoRoom/box/doingBox'''
const doingBox = () => {
const todos = useSelector((state:RootState) => state.doing)
const allTodos = todos.map((todo:any) => {
return(
<TodoCard
id={todo.id}
key={todo.id}
type="doing"
title ={todo.title}
manager = {todo.manager}
content = {todo.content}
deadline = {todo.deadline}
createDate = {todo.createDate}
dueDate = {todo.dueDate}
/>
)
})
return (
<TodoContainer>
<h1>Doing</h1>
{allTodos}
</TodoContainer>
)
}
todo박스, doing박스, done박스 각각 3개의 박스 컴포넌트를 만들고, 각 박스 컴포넌트는 해당되는 리덕스들에서 데이터를 가져와 TodoCard 컴포넌트 각각 만들어서 렌더링한다.
todoCard 컴포넌트
'''src/features/todoRoom/todoCard/todoCard.tsx'''
const TodoCard = (props: any) => {
//1. 함수 부분
const dispatch = useDispatch();
const [isFocusCard, setIsFocusCard] = useState(false);
const todoDoing = (id) => {
dispatch(addDoing(props))
dispatch(removeTodo(id))
}
const doingDone = (id) => {
dispatch(addDone(props))
dispatch(removeDoing(id))
}
const doneDoing = (id) => {
dispatch(addDoing(props))
dispatch(removeDone(id))
}
const doingTodo = (id) => {
dispatch(addTodo(props))
dispatch(removeDoing(id))
}
//2. 렌더링 부분
return (
<Button
onMouseEnter={() => {setIsFocusCard(true)}}
onMouseLeave={() => {setIsFocusCard(false)}}
>
{isFocusCard ?
( props.type =='todo' ?
(
<Focusing>
{/*<GridItemButton onClick={() => dispatch(removeTodo(props.id))}>삭제</GridItemButton>*/}
<WhenFocus onClick={() => dispatch(removeTodo(props.id)) }>삭제</WhenFocus>
<WhenFocus
onClick={() => todoDoing(props.id)}
style={{borderLeft: "1px dashed #A89797"}}
>Doing으로</WhenFocus>
</Focusing>
)
:
(props.type == 'doing' ?
<Focusing >
<WhenFocus onClick={() => doingTodo(props.id)}>Todo로</WhenFocus>
<WhenFocus
onClick={() => dispatch(removeDoing(props.id))}
style={{borderLeft: "1px dashed #A89797"}}
>삭제</WhenFocus>
<WhenFocus
onClick={() => doingDone(props.id)}
style={{borderLeft: "1px dashed #A89797"}}
>Done으로</WhenFocus>
</Focusing>
:
<Focusing>
<WhenFocus onClick={() => doneDoing(props.id)}>Doing으로</WhenFocus>
<WhenFocus
onClick={() => dispatch(removeDone(props.id))}
style={{borderLeft: "1px dashed #A89797"}}
>삭제</WhenFocus>
</Focusing>
)
)
:
<GridContainer a={isFocusCard} >
<GridTitle>{props.title}</GridTitle>
<GridContent>{props.content}</GridContent>
<GridManager>{props.manager}</GridManager>
<GridDeadline>{props.deadline}</GridDeadline>
<GridCreateDate>{props.createDate}</GridCreateDate>
<GridDueDate>{props.dueDate}</GridDueDate>
</GridContainer>
}
</Button>
);
}
1. 함수 부분
"(출발 리덕스)(도착 리덕스)"의 이름으로 이동 함수를 각각 만들고, 버튼에 바인딩해서 todoCard의 이동을 구현.
2. 렌더링 부분
부모의 props를 전달받아 해당 props의 name에 따라서, 마우스를 올렸을 때 각 카드에 버튼을 다르게 렌더링한다.
각 카드의 버튼 레이아웃은 Grid를 이용해 배치했다.
todoRoomForm 컴포넌트
''' src/features/todoRoom/todoRoomForm.tsx '''
const TodoRoomForm = () => {
const [todo, setTodo] = useState({
title: "임시 제목",
manager: "임시 담당자",
content: "임시 내용",
deadline: "2022-02-31",
createDate: Date(),
dueDate: "2022-02-28",
})
const textChange = (e) => {
const {name, value} = e.target;
setTodo({...todo, [name]:value})
}
const dispatch = useDispatch();
const todoDispatch =()=> {
const id = nanoid();
dispatch(addTodo({
id:id,
title:todo.title,
manager:todo.manager,
content:todo.content,
deadline:todo.deadline,
createDate:todo.createDate,
dueDate:todo.dueDate
}))
}
...
}
1. useState를 이용해 Todo객체를 만든다.
2. 폼 안에 각 input 태그에 id, name 값을 지정해주고, onChange를 이용해 input태그의 value값이 변하면, Todo객체에 바뀐 value값을 변경시킨다. (todo객체의 컨테이너를 벗겨주고, 그 안에 있는 속성값만 변경 후 setTodo로 반영한다.)
기타...
'''pages/_document.js'''
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
}
새로고침 시, styled-components에 입혀진 css가 적용이 안되, 임시로 구글링해서 삽입해주었다.
출처 : https://github.com/vercel/next.js/blob/main/examples/with-styled-components/pages/_document.js
자세한 코드....
https://github.com/RunLearn/super-todoapp/tree/abcxzy/todoroom
2024.03.07. 카테고리 이동
'프론트' 카테고리의 다른 글
리액트 - preventDefault, useState, useEffect, React.Fragment 등... (0) | 2022.02.06 |
---|