티스토리 뷰


이 글은

Tyler Hawkins의

React Clean Code / Simple ways to write better and cleaner code의

번역본 입니다.

원본 링크

 

React Clean Code

Simple ways to write better and cleaner code

betterprogramming.pub


 

 

클린 코드는 코드를 타이핑하는 것 그 이상입니다. 클린코드는 읽기 쉽고, 이해하기 쉬우며 잘 정돈 돼 있죠.

이 글에서 더 클린한 리액트 코드를 작성하는 8가지 방법에 대해 알아보겠습니다.

 

이 8가지 방법들은 그저 '제안'일 뿐이란걸 아셨으면 합니다. 이것들 중 어떤것은 동의하지 않는대도 괜찮습니다. 그러나, 이 방법들은 제 스스로 리액트 코드를 짜면서 발견한 유용한 방법들 입니다.

 

시작합시다!

 


1. 오직 하나의 상태만을 위한 상태 렌더링

 

만약 상태가 true일때만 무언가를 렌더하고 false일땐 아무것도 렌더링 하고싶지 않을 때,

삼항연산자를 사용하지 마세요. 대신 && 연산자를 사용하세요.

 

 

나쁜 예:

 

import React, { useState } from 'react'

export const ConditionalRenderingWhenTrueBad = () => {
  const [showConditionalText, setShowConditionalText] = useState(false)

  const handleClick = () =>
    setShowConditionalText(showConditionalText => !showConditionalText)

  return (
    <div>
      <button onClick={handleClick}>Toggle the text</button>
      {showConditionalText ? <p>The condition must be true!</p> : null}	// 역자주) 굳이 쓰지 않아도 되는 null을 넣지 맙시다
    </div>
  )
}

 

 

좋은 예:

 

import React, { useState } from 'react'

export const ConditionalRenderingWhenTrueGood = () => {
  const [showConditionalText, setShowConditionalText] = useState(false)

  const handleClick = () =>
    setShowConditionalText(showConditionalText => !showConditionalText)

  return (
    <div>
      <button onClick={handleClick}>Toggle the text</button>
      {showConditionalText && <p>The condition must be true!</p>}
    </div>
  )
}

 


2. 두 상태에서의 각기 다른 렌더링

 

만일 하나의 상태가 true일 때와 false일때 각각 다른 것을 렌더링 하려고 한다면,

삼항연산자를 이용하세요.

 

 

나쁜 예:

 

import React, { useState } from 'react'

export const ConditionalRenderingBad = () => {
  const [showConditionOneText, setShowConditionOneText] = useState(false)

  const handleClick = () =>
    setShowConditionOneText(showConditionOneText => !showConditionOneText)

  return (
    <div>
      <button onClick={handleClick}>Toggle the text</button>
      {showConditionOneText && <p>The condition must be true!</p>}
      {!showConditionOneText && <p>The condition must be false!</p>}
    </div>
  )
}

 

 

좋은 예:

 

import React, { useState } from 'react'

export const ConditionalRenderingGood = () => {
  const [showConditionOneText, setShowConditionOneText] = useState(false)

  const handleClick = () =>
    setShowConditionOneText(showConditionOneText => !showConditionOneText)

  return (
    <div>
      <button onClick={handleClick}>Toggle the text</button>
      {showConditionOneText ? (
        <p>The condition must be true!</p>
      ) : (
        <p>The condition must be false!</p>
      )}
    </div>
  )
}

 


3. 불리언 프로퍼티

 

truty 프로퍼티는 myTrutyProp처럼 값을 할당하지 않아도

프로퍼티 이름만으로도 컴포넌트에 할당할 수 있습니다.

myTrutyProp = {true} 라고 적을 필요가 없다는거죠.

 

 

나쁜 예:

 

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>
)

 

 

좋은 예:

 

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>
)

 


 

4. 문자열 프로퍼티

 

문자열 프로퍼티 값은 중괄호({ })나 백틱(` `)을 쓰지 않아도 큰따옴표(" ")만으로 할당할 수 있습니다.

 

 

나쁜 예:

 

import React from 'react'

const Greeting = ({ personName }) => <p>Hi, {personName}!</p>

export const StringPropValuesBad = () => (
  <div>
    <Greeting personName={"John"} />
    <Greeting personName={'Matt'} />
    <Greeting personName={`Paul`} />
  </div>
)

 

 

좋은 예:

 

import React from 'react'

const Greeting = ({ personName }) => <p>Hi, {personName}!</p>

export const StringPropValuesGood = () => (
  <div>
    <Greeting personName="John" />
    <Greeting personName="Matt" />
    <Greeting personName="Paul" />
  </div>
)

 


 

5. 이벤트 핸들러 함수

 

만약 이벤트 핸들러가 이벤트 객체에 대해 하나의 인수만을 갖는다면,

이벤트 핸들러 함수를 onChange = {handleChange} 이런식으로 선언해도 됩니다.

onChange = {e => handleChange(e)} 이런식으로 익명 함수로 묶지 않아도 됩니다.

 

 

나쁜 예:

 

import React, { useState } from 'react'

export const UnnecessaryAnonymousFunctionsBad = () => {
  const [inputValue, setInputValue] = useState('')

  const handleChange = e => {
    setInputValue(e.target.value)
  }

  return (
    <>
      <label htmlFor="name">Name: </label>
      <input id="name" value={inputValue} onChange={e => handleChange(e)} />
    </>
  )
}

 

 

좋은 예:

 

import React, { useState } from 'react'

export const UnnecessaryAnonymousFunctionsGood = () => {
  const [inputValue, setInputValue] = useState('')

  const handleChange = e => {
    setInputValue(e.target.value)
  }

  return (
    <>
      <label htmlFor="name">Name: </label>
      <input id="name" value={inputValue} onChange={handleChange} />
    </>
  )
}

 


 

6. 컴포넌트를 프로퍼티처럼 넘길때

 

컴포넌트를 프로퍼티로 다른 컴포넌트로 넘길 때,

함수 내에 넘겨진 컴포넌트가 어떠한 프로퍼티도 받지 않는다면 묶지 않아도 됩니다.

 

 

나쁜 예:

 

import React from 'react'

const CircleIcon = () => (
  <svg height="100" width="100">
    <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
  </svg>
)

const ComponentThatAcceptsAnIcon = ({ IconComponent }) => (
  <div>
    <p>Below is the icon component prop I was given:</p>
    <IconComponent />
  </div>
)

export const UnnecessaryAnonymousFunctionComponentsBad = () => (
  <ComponentThatAcceptsAnIcon IconComponent={() => <CircleIcon />} />
)

 

 

좋은 예:

 

import React from 'react'

const CircleIcon = () => (
  <svg height="100" width="100">
    <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
  </svg>
)

const ComponentThatAcceptsAnIcon = ({ IconComponent }) => (
  <div>
    <p>Below is the icon component prop I was given:</p>
    <IconComponent />
  </div>
)

export const UnnecessaryAnonymousFunctionComponentsGood = () => (
  <ComponentThatAcceptsAnIcon IconComponent={CircleIcon} />
)

 


 

7. Undefined 프로퍼티

 

Undefined 프로퍼티는 제외되기 때문에,

프로퍼티가 undefined인 것이 괜찮다면 undefined 폴백을 제공하는 것에 대해 걱정하지 않아도 됩니다.

 

 

나쁜 예:

 

import React from 'react'

const ButtonOne = ({ handleClick }) => (
  <button onClick={handleClick || undefined}>Click me</button>
)

const ButtonTwo = ({ handleClick }) => {
  const noop = () => {}

  return <button onClick={handleClick || noop}>Click me</button>
}

export const UndefinedPropsBad = () => (
  <div>
    <ButtonOne />
    <ButtonOne handleClick={() => alert('Clicked!')} />
    <ButtonTwo />
    <ButtonTwo handleClick={() => alert('Clicked!')} />
  </div>
)

 

 

좋은 예:

 

import React from 'react'

const ButtonOne = ({ handleClick }) => (
  <button onClick={handleClick}>Click me</button>
)

export const UndefinedPropsGood = () => (
  <div>
    <ButtonOne />
    <ButtonOne handleClick={() => alert('Clicked!')} />
  </div>
)

 


 

8. 이전 state에 의존하는 state를 세팅할 때

 

새 state가 이전 state에 의존한다면, 항상 state를 이전 state의 함수처럼 세팅하세요. 

리액트 state의 업데이트는 일괄 처리(batched) 될 수 있고,

업데이트를 이렇게 작성하지 않는 것은 예상치못한 결과를 불러 일으킬 수 있습니다.

 

 

나쁜 예:

 

import React, { useState } from 'react'

export const 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>
  )
}

 

 

좋은 예:

 

import React, { useState } from 'react'

export const PreviousStateGood = () => {
  const [isDisabled, setIsDisabled] = useState(false)

  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>
  )
}

 


아래의 세 방법들은 리액트에만 특정되지 않고 자바스크립트에서도 좋은 방법들 입니다(혹은 다른 프로그래밍 언어에게도 도움이 될 수 있겠네요).

 

  • 복잡한 로직을 명확히 이름지어진 함수로 만드세요. 
  • 매직 넘버(숫자가 무엇을 의미하는지 해석해야하는 수.)를 상수로 만드세요.
  • 명확히 이름 지어진 변수를 사용하세요.

 

즐거운 코딩 하세요!

반응형
댓글