본문 바로가기

모바일 개발/React Native-이론

계산기 - 클론코딩 (CustomHook 으로 지금까지 만든 부분 감싸기)

하나의 파일에 상태 변화 변수, 함수들과 View 부분이 혼재 하면, 유지 보수가 어렵다. 

그래서 상태 변화 변수, 함수들은 다른 파일로 빼주고, 그 파일 return 값에 태워서 View part 파일에게 건네다 주는  식으로 해야지 가독성이 좋다. 

우리는 우리가 만들었던 Hook들을 모아 나만의 Hook file을 만들 것이다. 

 

**주의점** 

Hook은 무조건 use라는 이름으로 시작해야함. Custom Hook (우리가 만들려는 Hook) file 도 예외 없음 

 

이번엔 계산기 만드는데 썼던 Hook 이니까 useCalculator라고 쓰자. 

이 안에 내용 다 넣고 return {} (객체) 안에 태워 보낸다. ()는 하나의 값 밖에 못 보내기 때문에 {}를 사용해야 한다.

()는 아무 의미 없고 그냥 여러 줄에 걸친 긴 하나의 명령문을 하나로 묶어주는 역할을 할 뿐이다.

값을 2개 이상 보낼 때는 {} 로 보내준다! 

import { useState } from "react";

export default () => {
  const [input, setInput] =useState(0); // 사용자가 첫 번째로 입력한 값
  const [currentOperator, setCurrentOperator] =useState(null); // 사용자가 첫번째로 입력한 연산자 
  const [result, setResult] =useState(null); // 사용자가 두 번째로 입력한 값
  const [tempInput, setTempInput] =useState(null); // 뒤로 사용자가 값을 더 안 넣고, =만 누를시 최근 입력한 값이 사용될 수 있게 임시 저장
  const [tempOperator, setTempOperator] =useState(null); // 사용자가 =만 누를 시 최근 입력한 연산자가 사용될 수 있게 임시 저장
  const [isClickedOperator, setIsClickedOperator] = useState(false)
  const [isClickedEqual, setIsClickedEqual] = useState(false)

  const hasInput = !!input;

  const onPressNum = (num) => {

    if (currentOperator && isClickedOperator) {
      setTempInput(num);
      setResult(input);
      setInput(num);
      setIsClickedOperator(false);

    } else{
      const newInput = Number(`${input}${num}`);
      setInput(newInput);
      setTempInput(newInput);
    }
  }

  const OnPressOperator = (operator) => {
    if(operator !== "="){
      setCurrentOperator(operator);
      setTempOperator(operator);
      setIsClickedOperator(true);
      setIsClickedEqual(false);
    }
    else{
      let finalResult = result;
      let finalInput = isClickedEqual? tempInput : input;
      let finalOperator = isClickedEqual? tempOperator : currentOperator;
      switch (finalOperator){
        case "+":
          finalResult = result + finalInput;
          break;    
        case "-":
          finalResult = result - finalInput;
          break;    
        case "*": 
          finalResult = result * finalInput;
          break;    
        case "/":
          finalResult = result / finalInput;
          break;    
        default:
          break;       
        }
      setResult(finalResult);
      setInput(finalResult);
      setIsClickedEqual(true);
      setCurrentOperator(null);
    }
  }

  const onPressReset = () => {
    if(hasInput){
      setInput(0);
    }else{
      setInput(0);
      setCurrentOperator(null);
      setResult(null);
      setTempInput(null);
      setTempOperator(null);
    }
  }

  return {
    input,
    currentOperator,
    result,
    tempInput,
    tempOperator,
    hasInput,
    onPressNum,
    OnPressOperator,
    onPressReset
  }
}

!받아올 때 주의점!

return을 {}으로 했으니까, 받아 쓸 때도 {} 로 해야한다. 

우리가 항상 useState 바로 만들 때 [ ] (배열)을 이용하던 것과 다름을 인지 하자.

 상태 변수로 쓰던 내용들이 전역 변수로 쓰던 색깔이나, 버튼 함수와 아무 관련이 없어서 깔끔하게 양분이 되었다. 

만약 상태변수에서도 해당 전역 변수 내용들을 쓴다면, useCalculator에도 전역변수를 넣던가, 아니면 import 해 오던가 ㄷ등 조치를 취해야 할 것이다.