본문 바로가기

모바일 개발/React Native-이론

계산기 클론코딩 - 계산 및 초기화 로직

0. Test 하는 값들이 눈에 보이도록 UI에 test 결과 창 만들기

test 결과창을 만들어 test 내용을 항시적으로 확인하는 것이 좋다. 

 main 함수에다가 만들어준다.

1. Button에서 함수 이용해 중복 코드 제거 

배열의 Map 함수 이용 

하나의 row에 들어가는 숫자 값들로 배열을 만들어주고 - [7,8,9]

배열의 내장 함수 map을 이용 

(num)은 배열의 원소가 차례대로 대입되는 인수 

text는 String 값을 받아야 하므로 `${}`이용해서 number 변수인 num을 String으로 형 변환 

 

이런 식으로 789, 456, 123의 코드를 줄이자.

2. 숫자 클릭 시 결과창에 찍히도록 

  const onPressNum = (num) => {
      setInput(num);
  }

해당 num 클릭시 상태창에서 보여주는 상태변수 input이 바뀌도록 설정. 

3. 숫자를 연이어 클릭할시 꼬리 물고 결과창에 찍히도록 (1 , 2 누르면 12가 되도록)

**Bad Case 1: 누르면 값이 더해져 버리는 경우

// onPressNum 내부
      const newInput = input + num;
      setInput(newInput);

이러면 누를 때마다 해당 숫자가 연이어 찍히지 않고 바로 더해져서 나와버린다. 

연이어 적히려면 Input과 num을 하나의 String이라 인식할 필요가 있다. 

**Bad Case 2: 0 누르고 9 누르면 9가 아니라 09가 찍히는 경우

// onPressNum 내부
      const newInput = `${input}${num}`;
      setInput(newInput);

이러면 위의 문제는 해결되고 연이어 찍히긴 하지만, 0 9 를 찍으면 9가 아니라 09가 나와버린다. 

이를 해결하려면 

**Good Case: 

  const onPressNum = (num) => {
      const newInput = Number(`${input}${num}`);
      setInput(newInput);
  }

String으로 연이어진 값을 한번 더 Number 변수로 형 변환 시켜주면 된다. 09란 숫자는 허용이 안되므로 Number 형 변환 시 앞의 0이 빠진다.

4. 연산자 부분 클릭시 boarder 가 굵어지도록 바꾸기 

버튼 부분에 isSelected 속성을 받아서 삼항 연산자 진행하면 된다. 

그렇다면 숫자 부분 버튼 태그에도 일일히 isSelected 속성을 달고 false 값을 줘야 하냐? No! 

그냥 isSelected를 태그에서 안 써주면 인수가 함수로 넘어갈 때, isSelected의 값은 undefined로 넘어간다. 

 

5.  연산자 부분 클릭 후 다시 숫자를 클릭하면 결과창이 초기화 되어 해당 숫자부터 다시 시작하도록 바꾸기

버튼 누르기 함수 바꾸기 

만약에 currentOperator에 값이 들어왔다면, 지금까지의 input 내용은 result로 옮기고, input은 값 새로 받고

currentOperator에 값이 없다면 원래처럼 계속 숫자 이어붙이기 

6. 연산자 로직 만들기 (= 눌렀을 때 계산이 되도록, = 아니면 currentOperator에 해당 값이 들어가도록)

만약 operator가 =이 아니라면 연산자 상태 변수에 현재 연산자를 집어넣고, 

만약 = 이라면 switch 구문으로 계산을 진행! 

** 주의 **

각 Case 마다 break 해줘야 하는 거 까먹지 말자. 해당 계산만 하고 Switch-Case문 빠져나오게, 아니면 밑으로 쭉 내려가서 전부 계산된다.

그리고 마지막 계산 결과를 

인풋 상태 변수 (화면에 나오는 변수)에 집어넣고, result에도 집어넣는다.

7. 초기화 함수 만들기

전부 리셋 시켜주면 된다.

 

** 잡다 지식 **

		/*함수 형태로 결과 부분에 다른 함수를 가져와 써도 되고 그냥 바로 함수 써버려도 된다.*/
		onPress={() => onPressReset()}
        /*onPress = {OnPressReset} 둘은 같은 말*/

-> 강사님 말씀을 잘못 이해함.
마지막 초기화 함수는 인수를 넣어 사용하지 않기 때문에
무한 루프가 돌 일이 없어서 
{() => onPress()}나
{onPress}나 같은 것이였음
인수를 넣어 하는 경우 클릭시에만 활성화 되라는 의미에서
{() => onPress(num)}으로 적어줘야 한다.

{onPress(num)} 이렇게 적으면 클릭을 안해줘도 계속 클릭한 것처럼 돌아가는 것이다!

 

8. 스스로 해보기

(1) 버튼 코드 중복 제거 

--> 틀린 점: 

배열을 이용한 map 함수 이용도 어떠한 기능을 통해 값을 내 보내는 것이니까 값을 쓸려면 전체를 {} 로 묶어야 한다. 
 

() => {}이걸로 결과 내보일려면 {return}을 써야 한다. () 이걸로 묶으면 해당 값 전체를 한줄로 읽고 retrun 없이 써도 된다. 
익명함수에서 () => 명령어 한 줄 이나 () => {return 명령어}나 같은 것을 이용한 것이다.

(2) 숫자 클릭시 결과창에 찍히도록

--> 틀린 점: 

Button 함수가 돌아가는 원리를 이해하지 못했다. 모든 함수는 반환 값이 곧 결과이다. OnPress는 누르면 반응하는 TouchableOpacity의 속성으로 넣으면 된다. 
                

나는 Button이 내가 만든 부분과 기본 코드가 혼재하고 있다고 생각하였고, 구현하지 않은 부분은 Button의 내장 코드가 해결해준다고 생각했다. 이는 잘못된 생각이다. 
                

Button이란 이름의 함수를 만들었으면 전부 자신이 다 구현해야 한다.

 


   Too Many Re-Render 오류가 났다. 
   이는 react가 state 변화 함수를 계속 반복해서 리랜더링 할때
               무한 루프에 빠져서 일어나는 오류이다.
               밑과 같이 적었으면 에러가 난다. 
              onPress={onPressNum(num)}

이렇게 적으면 클릭하지 않아도, num값을 상태변화 함수에 무한히 집어 넣는 것이 된다.
  해당 코드의 해결법은 
              사용자가 클릭했을 때만 반응하도록 밑과 같이 바꾸는 것이다.
              onPress={() => onPressNum(0)}

(3). 숫자 연달아 클릭시 그대로 숫자창에 찍히도록

(4). 연산자 클릭 시 boarder 가 굵어지도록 

(5). 연산자 클릭 후 다시 숫자 클릭하면 
   숫자 칸 초기화 되면서 금방 찍은 것만 찍히도록

(6). 연산자 로직 만들기. 
---> 생각치 못한 점: 
연산자 상태 변수와 함수의 인수로 들어오는 오퍼레이터값을
따로 쓸 수 있다는 생각을 못했다.
switch (명령 수행 기준이 되는 값) {
여러개를 나타내야 하니까 {}를 쓴다.
그리고 case "기준값": ~~ 객체 형태이다.
}

switch 안에 그냥 operator를 썼다. 
그러면 =을 누르는 순간 operator는 = 이 되니까
default로 넘어가서 그냥 값 출력하는 것 밖에 없다.


(7). 초기화 함수 만들기

-> 해당 내용에 적음 틀린점