코드를 작성하다보면 순간순간 고민되던 부분들이 있습니다.
지금 내가 쓴 코드를 나중에 다시 보거나 다른 사람들이 읽었을 때 과연 쉽게 이해할 수 있을까라는 생각을 하다가클린코드라는 글을 읽고, 다시 정리하는 글을 쓰게 되었습니다.
만약 상태가 true일 때만 무언가를 렌더링하고, false일 때 아무것도 렌더링 하고싶지 않을 경우,
삼항연산자보다는 &&연산자(논리 AND 연산자)
를 사용하세요.
👎 Bad
function App() {
return (
<div>
{showConditionalText ? <p>The condition must be true!</p> : null}
// 삼항연산자를 사용하면 null 같이 불필요한 코드가 늘어납니다.
</div>
)
}
👍 Good
function App() {
return (
<div>
{showConditionalText && <p>The condition must be true!</p>}
// 삼항연산자를 활용하면 조건별 렌더링을 더 가시적으로 표현할 수 있습니다.
</div>
)
}
만약 하나의 상태가 true일 때와 false일 때, 각각 다른 것을 렌더링 하려고 한다면,
삼항연산자
를 사용하세요.
👎 Bad
function App() {
return (
<div>
{showConditionOneText && <p>The condition must be true!</p>}
{!showConditionOneText && <p>The condition must be false!</p>}
</div>
)
}
👍 Good
function App() {
return (
<div>
{showConditionOneText ? (
<p>The condition must be true!</p>
) : (
<p>The condition must be false!</p>
)}
</div>
)
}
truty 프로퍼티는 myTrutyProp처럼 따로 값을 할당하지 않아도 prop만으로 컴포넌트에 참으로 평가되는 값을 제공할 수 있는 경우가 있습니다.
예를 들어, myTrutyProp = {true}
라고 적을 필요가 없습니다.
👎 Bad
import React from 'react'
const HungryMessage = ({ isHungry }) => (
<span>{isHungry ? 'I am hungry' : 'I am full'}</span>
)
export const BooleanPropBad = () => (
<div>
<span>
<b>This person is hungry: </b>
</span>
<HungryMessage isHungry={true} />
<br />
<span>
<b>This person is full: </b>
</span>
<HungryMessage isHungry={false} />
</div>
)
👍 Good
import React from 'react'
const HungryMessage = ({ isHungry }) => (
<span>{isHungry ? 'I am hungry' : 'I am full'}</span>
)
export const BooleanPropGood = () => (
<div>
<span>
<b>This person is hungry: </b>
</span>
<HungryMessage isHungry />
<br />
<span>
<b>This person is full: </b>
</span>
<HungryMessage isHungry={false} />
</div>
)
문자열 프로퍼티 값은 중괄호{}
나 백틱``
을 쓰지 않아도 쌍 따옴표 만으로 할당할 수 있습니다.
👎 Bad
const Greeting = ({ personName }) => <p>Hi, {personName}!</p>
function StringPropValuesBad() {
<div>
<Greeting personName={"John"} />
<Greeting personName={'Matt'} />
<Greeting personName={`Paul`} />
</div>
}
👍 Good
const Greeting = ({ personName }) => <p>Hi, {personName}!</p>
function StringPropValuesGood () {
<div>
<Greeting personName="John" />
<Greeting personName="Matt" />
<Greeting personName="Paul" />
</div>
}
만약에 이벤트 핸들러가 이벤트 객체에 대해 하나의 인수만을 갖는다면,
이벤트 핸들러 함수를 onChange={handleChange} 이런식으로 선언해도 됩니다.
onChange={e => handleChange(e)}이런식으로 익명 함수로 묶지 않아도 됩니다.
👎 Bad
function App() {
const [inputValue, setInputValue] = useState("");
const handleChange = event => {
setInputValue(event.tartget.value);
}
return(
<>
<input value={inputValue} onChange={e => handleChange(e)} />
</>
);
}
👍 Good
function App() {
const [inputValue, setInputValue] = useState("");
const handleChange = event => {
setInputValue(event.tartget.value);
}
return(
<>
<input value={inputValue} onChange={handleChange} />
</>
);
}
어떤 컴포넌트(B)에 prop으로 또 다른 컴포넌트(A)를 전달하는 경우,
전달되는 컴포넌트(A)가 아무 props를 받지 않는다면 굳이 함수로 감쌀 필요없이 컴포넌트명만 전달해도 됩니다.
👎 Bad
function CircleIcon() {
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
)
function ComponentThatAcceptsAnIcon ({ IconComponent }){
<div>
<p>Below is the icon component prop I was given:</p>
<IconComponent />
</div>
}
function UnnecessaryAnonymousFunctionComponentsBad() {
{/* (역주) CircleIcon은 아무런 인자를 받지 않는데도 함수로 감싸서 전달 */}
<ComponentThatAcceptsAnIcon IconComponent={() => <CircleIcon />} />
}
👍 Good
function CircleIcon() {
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
)
function ComponentThatAcceptsAnIcon ({ IconComponent }){
<div>
<p>Below is the icon component prop I was given:</p>
<IconComponent />
</div>
}
function UnnecessaryAnonymousFunctionComponentsBad() {
{/* (역주) 아무런 인자를 받지 않는 CircleIcon를 함수로 싸지 않고 컴포넌트명으로 전달 */}
<ComponentThatAcceptsAnIcon IconComponent={CircleIcon} />
}
Undefined props는 제외됩니다.
만약 어떤 props가 undefined
로 제공되어도 컴포넌트 작동에 문제가 없다면,
props값으로 undefined
를 전달하는 것에 대한 대비책을 걱정할 필요는 없습니다.
👎 Bad
function ButtonOne({ handleClick }) {
<button onClick={handleClick || undefined}>Click me</button>
}
function ButtonTwo({ handleClick }) {
const noop = () => {}
return <button onClick={handleClick || noop}>Click me</button>
}
function UndefinedPropsBad() {
<div>
<ButtonOne />
<ButtonOne handleClick={() => alert("Clicked!")} />
<ButtonTwo />
<ButtonTwo handleClick={() => alert("Clicked!")} />
</div>
}
👍 Good
function ButtonOne({ handleClick }) {
<button onClick={handleClick}>Click me</button>
}
function UndefinedPropsGood() {
<div>
<ButtonOne />
<ButtonOne handleClick={() => alert("Clicked!")} />
</div>
}
새 state가 이전 state에 의존한다면, 이전 state 값을 이용한 함수(updater 함수)를 전달해야 합니다.
React state의 업데이트는 일괄적으로 처리될 수도 있고,
업데이트를 이렇게 작성하지 않는 것은 예상치 못한 결과를 불러 일으킬 수 있습니다.
👎 Bad
function PreviousStateBad() {
const [isDisabled, setIsDisabled] = useState(false);
// (역주) 이전 값에 의존하는 상태갱신 함수에 갱신결과값만을 전달하면
const toggleButton = () => setIsDisabled(!isDisabled)
// (역주) 이 함수의 결과가 정상적으로 작동하지 않음을 알 수 있습니다.
const toggleButton2Times = () => {
for (let i = 0; i < 2; i++) {
toggleButton()
}
}
return (
<div>
<button disabled={isDisabled}>
I'm {isDisabled ? 'disabled' : 'enabled'}
</button>
<button onClick={toggleButton}>Toggle button state</button>
<button onClick={toggleButton2Times}>Toggle button state 2 times</button>
</div>
)
}
👍 Good
function PreviousStateGood() {
const [isDisabled, setIsDisabled] = useState(false);
// (역주) 상태갱신 함수의 인자로 이전 값을 인자로 하는 updater 함수를 전달하면
const toggleButton = () => setIsDisabled(isDisabled => !isDisabled)
// (역주) 아래 함수가 의도한대로 동작함을 알 수 있습니다.
const toggleButton2Times = () => {
for (let i = 0; i < 2; i++) {
toggleButton()
}
}
return (
<div>
<button disabled={isDisabled}>
I'm {isDisabled ? 'disabled' : 'enabled'}
</button>
<button onClick={toggleButton}>Toggle button state</button>
<button onClick={toggleButton2Times}>Toggle button state 2 times</button>
</div>
)
}