4일차(3.1~3.3)
01. 컴포넌트 생성
GlobalStyle- 활용 검색
// App.js
const GlobalStyle = createGlobalStyle`
body {
background-color: #e9ecef;
}
`
// index.css에 추가하지 않고 전역 스타일을 설정할 수 있다
function App() {
return (
<div className='App'>
<GlobalStyle />
<TodoTemplate>
<TodoHead />
<TodoList />
<TodoCreate />
</TodoTemplate>
</div>
)
}
전부 styledComponent로 만들지 않고, 자식에게 className을 주어서 상속문법으로 적용시킬 수도 있다
조건부 스타일링을 할 필요가 없고, 기능적으로도 크게 중요하지 않은 내용이라면 CSS Selector 를 사용하는 것도 좋은 방법이다
const TodoHeadBlock = styled.div`
padding-top: 48px;
padding-left: 32px;
padding-right: 32px;
padding-bottom: 24px;
border-bottom: 1px solid #e9ecef;
h1 {
margin: 0;
font-size: 36px;
color: #343a40;
}
.day {
margin-top: 4px;
color: #868e96;
font-size: 21px;
}
.tasks-left {
color: #20c997;
font-size: 18px;
margin-top: 40px;
font-weight: bold;
}
`
컴포넌트 셀렉터
const TodoItemBlock = styled.div`
display: flex;
align-items: center;
padding-top: 12px;
padding-bottom: 12px;
&:hover {
${Remove} { // 컴포넌트 셀렉터
display: initial;
}
}
`
리액트 아이콘 라이브러리
import { MdDone, MdDelete } from 'react-icons/md'
정적인 속성들과 동적인 속성을 구분해서 따로 작성하는게 더 깔끔한 것 같다
const CircleButton = styled.button`
background: #38d9a9;
&:hover {
background: #63e6be;
}
&:active {
background: #20c997;
}
z-index: 5;
cursor: pointer;
width: 80px;
height: 80px;
display: block;
align-items: center;
justify-content: center;
font-size: 60px;
position: absolute;
left: 50%;
bottom: 0px;
transform: translate(-50%, 50%);
color: white;
border-radius: 50%;
border: none;
outline: none;
display: flex;
align-items: center;
justify-content: center;
transition: 0.125s all ease-in;
${(props) =>
props.open &&
css`
background: #ff6b6b;
&:hover {
background: #ff8787;
}
&:active {
background: #fa5252;
}
transform: translate(-50%, 50%) rotate(45deg);
`}
`
02. Context API 를 활용한 상태 관리
- context.js파일을 만든다
- 초기데이터를 불러오고 reducer함수를 만들어준다
- state와 함수들 각각의 context를 만든다
- Provider컴포넌트를 만든다
- 인자로 children가 들어가는데, 값을 사용할 범위를 지정해주는 것
- useReducer를 사용해 값을 꺼내온다(useState를 사용할 수도 있음)
- 반환값은 인자를 감싼 각 값이 전달된 context.Provider컴포넌트들이다
- context파일 안에서 useContext사용해 직접 값 할당을 받은 후 내보내서 사용할 수도 있다
- App컴포넌트에서 Provider컴포넌트를 import해서 사용할 범위만큼 컴포넌트들을 감싸준다
03. 기능 구현하기
Date 의 toLocaleString
첫번째 인자: 사용할 언어
두번째 인자: 어떤 값을 어떤 형식으로 가져올 건지에 대한 객체 형식의 옵션
const today = new Date()
// 년, 월, 일
const dateString = today.toLocaleDateString('ko-KR', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
// 요일
const dayName = today.toLocaleDateString('ko-KR', { weekday: 'long' })
useReducer의 dispatch
정보를 받아 해당하는 setState를 일으켜주는 함수
const dispatch = useTodoDispatch()
const onToggle = () => dispatch({ type: 'TOGGLE', id }) // 정보를 받아 setState를 일으켜주는 함수
const onRemove = () => dispatch({ type: 'REMOVE', id })
useRef 전역 변수의 값 변경
const onSubmit = (e) => {
e.preventDefault()
dispatch({
type: 'CREATE',
todo: { id: nextId.current, text: value, done: false },
})
setValue('') //제출하고 난 뒤, input값을 비워줌
setOpen(false) // 제출하고 난 뒤, input창을 닫아줌
nextId.current += 1 // 전역 변수인 nextId의 값을 +1 해줌 - 전역 변수이기 때문에 가능한듯(setter함수를 안쓰기 때문에)
}
여러 컴포넌트를 조건부 렌더링하는 법
return (
<>
{open && (
<InsertFormPositioner>
<InsertForm onSubmit={onSubmit}>
<Input
autoFocus
placeholder='할 일을 입력 후, Enter를 누르세요'
onChange={onChange}
value={value}
/>
</InsertForm>
</InsertFormPositioner>
)}
<CircleButton onClick={onToggle} open={open}>
<MdAdd />
</CircleButton>
</>
)
이해 안 가는 부분
그리고 맨 마지막 줄에서는 React.memo
로 감싸주었는데요, 이렇게 함으로써 TodoContext 에서 관리하고 있는 state
가 바뀔 때 때 TodoCreate 의 불필요한 리렌더링을 방지 할 수 있습니다. 만약 우리가 Context 를 하나만 만들었다면 이런 최적화를 하지 못하게 됩니다.
알게된 점
- emotion에서 css쓰는 법
- outline - 레이아웃에 영향 안줌
- autoFocus - 속성으로 넣어주면 자동으로 focus
- provider는 최소한만 사용, 너무 겹쳐서쓰면 렌더링문제가 발생
→ 상태가 담겨있는 것 만으로도 사용을 안했어도 상태가 바뀌면 리렌더링이 된다?
Author And Source
이 문제에 관하여(4일차(3.1~3.3)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yooon26/4일차3.13.3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)