백엔드 개발자 프론트 도전기 feat.리엑트 [2]
- Study/FrontEnd
- 2021. 1. 8. 23:52
SASS라고??
리액트를 하다 보니 SASS라는 단어가 나왔다. 풀 네임은 Syntactically Awesome Style Sheets인데 멋진 스타일 시트 정도로 해석할 수 있다 ㅋㅋ
SASS는 CSS pre-processor로 약간 코딩하는 방식으로 CSS를 만들면 SASS가 CSS로 변환하는 역할을 해준다. 그래서 SASS로 작성한 문서는 브라우저에서는 단순히 CSS로만 보이게 된다. 초창기에는. sass파일만 지원했는데 지금은. scss파일도 지원한다. 두 개가 다 똑같은 sass 긴 한데. scss가 문법이 좀 더 css와 비슷해서 사용하기 쉽다.
일단 sass쓰려면 따로 패키지를 설치해야 한다.
(* 5.0.0 버전이 있긴 한데 작동하지 않는다. 4.14.1을 선택하자)
그리고는. scss파일을 만들어서 입력하면 된다.
아래는 여러가지 버튼 스타일을 저장한. scss파일이다.
$blue: #228be6;
$gray: #495057;
$pink: #f06595;
@mixin button-color($color) {
background: $color;
&:hover {
background: lighten($color, 10%);
}
&:active {
background: darken($color, 10%);
}
}
.Button {
display: inline-flex;
color: white;
font-weight: bold;
outline: none;
border-radius: 4px;
border: none;
cursor: pointer;
// 사이즈 관리
&.large {
height: 3rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.25rem;
}
&.medium {
height: 2.25rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1rem;
}
&.small {
height: 1.75rem;
font-size: 0.875rem;
padding-left: 1rem;
padding-right: 1rem;
}
// 색상 관리
&.blue {
@include button-color($blue);
}
&.gray {
@include button-color($gray);
}
&.pink {
@include button-color($pink);
}
& + & {
margin-left: 1rem;
}
}
@mixin이라는 게 처음 나오는데 css의 함수 같은 느낌이다. 입력 갑을 주면 해당 입력으로 적당한 css 아웃풋을 가져온다.
classname 패키지
아래는 Button.js의 코드인데 classnames란 함수를 사용했다.
css에 class 넣을 때 xxx yyy dd 이런 식으로 여러 개를 넣을 때가 있는데, 컴포넌트의 인자 값으로 들어오는 값들을 나열하기 위해 배열을 쓰지 않고 classnames를 사용해 쓰면 알아서 한 칸씩 띄워서 입력해준다. classname도 패키지만 설치해주면 바로 사용할 수 있다.
import React from 'react';
import classNames from 'classnames';
import './Button.scss'
function Button({children, size, color, outline}){
return (
<button className={classNames('Button', size, color, outline)} >{children}</button>
);
}
Button.defaultProps = {
size: 'medium',
color: 'blue'
}
export default Button
CSS Module
최근에 프론트 몇 개 만들면서 느낀 것이 class이름이 중복될 수 있다. 그럼 꼬인다 ㅋㅋ
예를 들어. sample이라고 해놓고 p.sample이라고 새로 지정하면. sample은 글로벌이기 때문에 p.sample은 실제로. sample + p.sample이 된다. (당연한 소리지만,,, 처음 하면 모른다고)
그밖에도 기존에 개발되어있는 곳에 새로운 css를 넣을 때 이름이 있는지 없는지 잘 찾아봐야 하는데, CSS Module을 사용하면 겹치지 않게 이름을 잘 생성해준다.
styled-components
CSS in JS라고 해서 js에서 CSS를 만드는 기술이다.
(*styled-components 패키지 설치해야 한다)
//App.js
import React from 'react';
import styled from 'styled-components';
const Circle = styled.div`
width: 5rem;
height: 5rem;
background: ${props => props.color || 'black'};
border-radius: 50%;
`;
function App() {
return <Circle color="blue"/>;
}
export default App;
위처럼 .js에서 css를 활용한 스타일을 적용할 수 있다.
styled-components에 ThemeProvider라는 함수도 제공하는데, html 라인에서 palette에서 색을 빼올 수 있다. 물론 이렇게 간단하게 쓰지 않고 전체적으로 관리하는 공통 css를 theme로 관리해서 사용할 수도 있다.
공식 홈피 - styled-components: Advanced Usage (styled-components.com)
Todo 만들어보기
너무 기본 문법만 배워서 잘 모르겠다. 어떻게 쓰는지도 모르겠고, 맨땅에 만들 수 있을지도 모르겠고 ㅋㅋㅋ
일단 뭐라도 만들어보면서 해야지
일단 예제에서는 프론트로만 ToDo를 만들었는데, 궁극적인 목표는 뒤에 백엔드를 붙이는 것이다.
먼저 react-icons, styled-components 패키지를 설치하고 시작.
먼저 ui부터 그렸는데, 디자인이 없이 시작하려니 단순히 코드를 복붙 해서 가져오는 것밖에 안 하고 있어서 뭔가 이상하다.
실제로는 제플린을 보면서 한줄한줄 쳐서 화면을 완성했는데, 이거 뭐 기획 없고 디자인 없고 바로 화면 그릴려니 ㅋㅋ
잘하는 FE개발자들은 바로바로 나오려나..?
암튼 화면은 일단 그림
(화면까지 소스 : tkdlek11112/todo-list at 화면UI (github.com))
Context API를 다시 한번 복습해보자면 상태를 관리하기 위해 useReducer를 만들었고 Context로 만들어서 Provider로 감싸면 그 안에서는 Context를 사용할 수 있었다.
function todoReducer(state, action){
switch (action.type){
case 'CREATE':
return state.concat(action.todo);
case 'TOGGLE':
return state.map(todo => todo.id === action.id ? {...todo, done: !todo.done} : todo);
case 'REMOVE':
return state.filter(todo => todo.id !== action.id);
default:
throw new Error('정의되지 않은 액션이 들어왔어욤');
}
}
const TodoStateContext = createContext();
const TodoDispatchContext = createContext();
export function TodoProvider({children}){
const [state, dispatch] = useReducer(todoReducer, initialTodos);
return (
<TodoStateContext.Provider value={state}>
<TodoDispatchContext.Provider value={dispatch}>
{children}
</TodoDispatchContext.Provider>
</TodoStateContext.Provider>
);
}
이렇게 reducer를 만들고 createContext를 이용해서 State와 Dispatch를 만들어서 Provider value로 넘겨주면 다른 곳에서 state와 dispatch를 사용해 context를 사용할 수 있다.
import React, { useContext } from 'react';
import { TodoStateContext, TodoDispatchContext } from '../TodoContext';
function Sample() {
const state = useContext(TodoStateContext);
const dispatch = useContext(TodoDispatchContext);
return <div>Sample</div>;
}
근데 js에서 제일 적은 안 되는 건 list를 뿌릴 때 iter를 돌리는 게 map이라는 함수를 이용해서 돌린다는 것이다. 이게 for문인지 while인지 처럼 직관적이지 않다 ㅋㅋ 뭐 익숙해지면 비슷해지려나..
function TodoList(){
const todos = useTodoState()
return (
<TodoListBlock>
{todos.map(todo => (
<TodoItem key={todo.id} id={todo.id} text={todo.text} done={todo.done}/>
))};
</TodoListBlock>
);
}
여차 저차 해서 완성!
'Study > FrontEnd' 카테고리의 다른 글
[Flutter] 플러터 레이아웃 튜토리얼 진행 (0) | 2021.05.23 |
---|---|
[Flutter] 튜토리얼 앱 만들기 (0) | 2021.05.03 |
react - django, cors 문제. django-cors-headers를 깔아도 문제가 발생할 때 (0) | 2021.04.21 |
[Flutter] 설치하기 (0) | 2021.04.02 |
백엔드 개발자 프론트 도전기 feat.리엑트 [1] (0) | 2021.01.08 |