클린코드

리액트 클린 코드 - (1)

여행 가고싶다 2023. 4. 19. 14:52

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

true일 때만 render하고 false일 땐 render하고 싶지 않을 때, 삼향연사자보다는 &&연산자로

 

나쁜 예 :

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}	) <<<<<<
    </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. 두 상태에서의 각기 다른 렌더링

이럴 때는 삼항 연산자를 사용합시다

 

나쁜 예: 

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. 이벤트 핸들러 함수

만약 이벤트 핸들러가 이벤트 객체에 대해 하나의 인수만을 갖는다면, 이벤트 핸들러 함수를 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} /> <<<<<<
    </>
  )
}

 

4. 이전 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>
  )
}
useState 훅에서 상태 변경 함수는 이전 상태 값을 받는 함수를 인자로 받습니다. 이전 상태 값을 받는 함수를 이용하면 비동기로 동작하는 React의 setState 메서드와 달리, 최신의 상태 값을 보장할 수 있습니다.

반면에, const toggleButton = () => setIsDisabled(!isDisabled) 처럼 이전 상태 값을 인자로 받지 않고, 현재 상태 값을 직접 참조하는 방식은, 여러 상태 변경 사항이 발생하는 경우 각각의 상태가 최신 값을 반영하는 것을 보장하지 않습니다.

예를 들어, toggleButton2Times 함수에서 toggleButton 함수를 두 번 호출하는데, 첫 번째 호출 이후 상태가 변경될 때까지 시간이 걸릴 수 있으므로, 두 번째 호출은 최신 상태를 반영하지 않을 가능성이 있습니다.

따라서, 이전 상태 값을 인자로 받는 함수를 사용하여 상태 값을 변경하는 것이 더욱 안전하고 예측 가능한 코드를 작성하는 데 도움이 됩니다.