개발은 여러명이서 함께하는 것
좋은 코드는 누가 보아도 이해하기 쉽고, 가독성이 좋아야 한다.
reset.scss, common.scss의 위치는 index.js에서 한번만
// style/variables.scss
$theme-background: #f6f4f1;
$theme-light-gray-background: #faf9f8;
$theme-blue: #007aff;
$theme-gray-strong: #888888;
$theme-gray-normal: #cccccc;
$theme-gray-light: #eeeeee;
$theme-white: #fff;
$theme-black: #1c1c1e;
$theme-red: #ff0000;
@import "../../styles/variables.scss";
.main {
.title {
color: $theme-red;
}
}
귀찮다고 common.scss 에 프로젝트 전체적으로 적용되는 스타일 과 변수 / 믹스인을 함께 선언 금지
만약 그렇게 하게 되면 변수를 사용하기 위해 각 scss 파일에서 common.scss 를 import 할텐데, 이때 전체적으로 적용되는 스타일이 중복해서 적용
// Bad common.scss 🙅♂️ 🙅♂️ 🙅♂️
$theme-background: #f6f4f1;
$theme-light-gray-background: #faf9f8;
$theme-blue: #007aff;
$theme-gray-strong: #888888;
$theme-gray-normal: #cccccc;
$theme-gray-light: #eeeeee;
$theme-white: #fff;
$theme-black: #1c1c1e;
$theme-red: #ff0000;
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
자바 스크립트는 모듈 시스템을 통해 모든 css파일들이 합쳐지기 떄문에, 하나의 css에서 작성한 코드가 의도치 않게 다른 파일에 있는 요소에 영향을 줄 수 있다.
Layout Properties (position, float, clear, display)
Box Model Properties (width, height, margin, padding)
Visual Properties (color, background, border, box-shadow)
Typography Properties (font-size, font-family, text-align, text-transform)
Misc Properties (cursor, overflow, z-index)
인라인 스타일은 꼭 필요한 경우가 아니라면 지양해야한다. 가장 높은 우선순위를 가지고 있기 때문에 나중에ㅜ 유지보수를 어렵게 만든다.
// inline style 사용 🙅♂️
<button
onClick={handleCommentInputButton}
style={{ color: isCommentButtonActive ? "#0095f6" : "#b5e1ff" }}
>
로그인
</button>
// className 사용 🙆♂️
<button
onClick={handleCommentInputButton}
className={isCommentButtonActive ? "activated" : "deactivated"}
>
로그인
</button>
.activated {
color: #0095f6;
}
.deactivated {
color: #b5e1ff;
}
비구조화 할당(구조분해 할당)은 객체, 배열에 적용할 수 있는 ES6 문법이다.
이 기능을 통해 긴 코드를 간결하게 사용할 수 있다.
// 비구조화 할당 미적용
const handlePasswordInput = event => {
setPassword(event.target.value);
...
}
// 비구조화 할당 적용
const handlePasswordInput = event => {
const { value } = event.target;
setPassword(value);
...
}
핸들러 함수에서 뿐만 아니라 함수 컴포넌트 바디에서도 props객체에서 비구조화 할당을 적용해 코드를 간결하게 쓸 수 있다.
function PasswordInput (props) {
return (
<input value={props.passwordValue} onClick={props.handlePasswordInput}/>
)
}
// 비구조화 할당 적용
function PasswordInput (props) {
const { passwordValue, handlePasswordInput } = props;
return (
<input value={passwordValue} onClick={handlePasswordInput}/>
)
}
// props 자리에서 바로 비구조화 할당을 할 수도 있습니다.
function PasswordInput ({ passwordValue, handlePasswordInput }) {
return (
<input value={passwordValue} onClick={handlePasswordInput}/>
)
}
Before 🙅♂️
if (event.target.value.includes("@") && event.target.value.length >= 5) {
setIsIdValid(true);
} else {
setIsIdValid(false);
}
// After 🙆♂️
const { value } = event.target;
const isIdInputValid = value.includes("@") && value.length >= 5;
setIsIdValid(isIdInputValid);
// named export (vs. default export)
export const INFO_LIST = [
{id: 1, content: "도움말"},
{id: 2, content: "홍보 센터"},
{id: 3, content: "API"},
{id: 4, content: "채용정보"},
{id: 5, content: "개인정보처리방침"},
{id: 6, content: "약관"},
{id: 7, content: "위치"},
{id: 8, content: "인기 계정"},
]
// Footer.js (Footer 컴포넌트)
import { INFO_LIST } from './footerData.js'
return (
...
{INFO_LIST.map(info => {
return (
<li key={info.id}>
<a href="">{info.content}</a>
</li>
)
});
return (
<li key={el.id}>
<span>{el.content}</span>
</li>
)
})
위 상황에서 INFO_LIST 변수를 함수 컴포넌트 바디에서 선언할 경우 컴포넌트가 render 될 때마다 새로운 변수가 계속 선언되기 때문에, 값이 변하지 않는 변수는 컴포넌트 밖에서 선언합니다.
단 가독성을 위해 상단에 작성하지 말고 코드의 하단의 위치하도록 한다.
input 태그에는 name 이라는 속성이 있습니다. 말 그대로 input 태그에 이름을 지어 주는 건데요. 이 name 속성 덕분에 여러 개의 input handler를 하나로 합칠 수 있다
// 비슷하게 생긴 코드가 보이면 줄이는 방법에 대해 고민해보시기 바랍니다!
// Before
const [inputValues, setInputValues] = useState({
email: "",
password: "",
});
const handleEmail = event => {
const { value } = event.target;
setInputValues({
...inputValues,
email: value,
})
}
const handlePassword = event => {
const { value } = event.target;
setInputValues({
...inputValues,
password: value,
})
}
return (
...
<input
className="emailInput"
type="text"
onChange={handleEmail}
/>
<input
className="passwordInput"
type="password"
onChange={handlePw}
/>
...
);
}
// After
const [inputValues, setInputValues] = useState({
email: "",
password: "",
});
const handleInput = event => {
const { name, value } = event.target;
setInputValues({
...inputValues,
[name]: value,
})
}
return (
...
<input
className="emailInput"
name="email"
type="text"
onChange={handleInput}
/>
<input
className="passwordInput"
name="password"
type="password"
onChange={handleInput}
/>
...
);
name 속성의 값은 value처럼 event.target으로 가져올 수 있다. (event.target.name)
name 속성은 오직 input 태그에서만 사용할 수 있습니다. 다른 태그에서 사용하려고 시도금지
a tag는 사용하면 새로고침 하는 것처럼 html을 새로 다 받아 오는 반면, Link 를 사용하면 컴포넌트만 바꿔준다. 렌더링 최적화를 위해서 Link 사용하자
외부 사이트 이동시에만 a 링크 사용
라이브러리
컴포넌트
함수, 변수 및 설정 파일
사진 등 미디어 파일(.png)
css 파일 (.scss)
state의 업데이트는 렌더링 발생.
만약 state로 관리하지 않아도 되는 값을 state로 관리할 경우, 일어나지 않아도 되는 렌더링이 발생하게 됩니다. 따라서 불필요한 state 값들은 제거
부모로부터 전달받는 props
시간이 지나도 변하지 않는 값 (UI 변화에 관여하지 않는 값)
컴포넌트 안의 다른 state 나 props 로 계산 가능한 값