본문 바로가기

프론트

리액트 스터디 병합 전, 정리

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. 카테고리 이동