계산기 프로젝트를 진행하면서 알게된 내용들을 작성하였다.
Double exclamation !!
연산자
느낌표 2개를 연달아 사용하는 !!
연산자는 확실한 boolean결과(true 또는 false)를 얻기위해 사용한다.
기존의 느낌표 연산자!
는 true를 false로, false를 true로 바꾸는 역할이었다면,
!!
는 변수에 값이 존재할 경우(String, Number, Boolean 등)에는 true를 반환하고, undefined나 null값은 false값을 반환한다.
프로젝트에서 사용한 코드인데, 두 코드는 같은역할을 한다.
1
const hasInput = input ? true : false;
1
const hasInput = !!input;
인자없는 함수
1
onPress={()=>onPressReset()}
이처럼 인자를 받지 않는 함수는 다음처럼 간단하게 줄여서 작성할 수 있다.
1
onPress={onPressReset}
변수 -> String
변수를 화면에 출력하거나, String의 특성을 사용하고싶을 때는 String으로 변환이 필요하다.
두 가지 방법으로 변환이 가능하다.
- String(변수명)
- `${변수명}`
Test 코드
개발에 필요한 state값들을 확인하기 위해 화면에 test코드를 작성하였다.
1
2
3
4
5
<Text>input:{input}</Text>
<Text>currentOperator:{currentOperator}</Text>
<Text>result:{result}</Text>
<Text>tempInput:{tempInput}</Text>
<Text>tempOpertor:{tempOpertor}</Text>
개발상황이 아닐 경우에는 화면에 이런 test코드는 보여지지 않아야하므로 __DEV__
를 입력하여 개발환경에서만 출력되도록 설정하면된다.
앱 시뮬레이터나 usb로 연결한 기기일 경우 true값을 반환하고, 앱 번들로 제출한 배포버전에서는 false값을 반환한다.
1
2
3
4
5
6
7
8
9
{ __DEV__ && (
<>
<Text>input:{input}</Text>
<Text>currentOperator:{currentOperator}</Text>
<Text>result:{result}</Text>
<Text>tempInput:{tempInput}</Text>
<Text>tempOpertor:{tempOpertor}</Text>
</>
)}
Refactoring
반복되는 버튼 컴포넌트를 map을 사용하여 리팩토링
- 기존 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
<ButtonContainer> <Button type="num" text="7" onPress={()=>null} flex={1} /> <Button type="num" text="8" onPress={()=>null} flex={1} /> <Button type="num" text="9" onPress={()=>null} flex={1} /> <Button type="operator" text="X" onPress={()=>null} flex={1} /> </ButtonContainer>
- 리팩토링 후 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<ButtonContainer> {[7,8,9].map((num)=>( <Button type="num" text={`${num}`} onPress={()=>null} flex={1} /> ))} <Button type="operator" text="X" onPress={()=>null} flex={1} /> </ButtonContainer>
커스텀 Hook을 만들어 화면뷰와 기능구현함수들을 분리하여 가독성을 높혔다.
- 기존 코드는 화면구현과 기능구현을 한 파일 내에서 진행했었다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
export default () => { const [input,setInput] = useState(0); const [currentOperator, setCurrentOperator] = useState(null); const [result,setResult] = useState(null); [ ...생략 ] const onPressOperator = (operator) =>{ if(operator !== "="){ setCurrentOperator(operator); setIsClickedOperator(true); setIsClickedEqual(false); }else{ let finalResult = result; const finalInput = isClickedEqual ? tempInput : input; const finalOperator = isClickedEqual ? tempOpertor : 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); setTempInput(finalInput); setCurrentOperator(null); setTempOperator(finalOperator); setIsClickedEqual(true); } } const onPressReset = ()=>{ if(hasInput){ setInput(0); }else{ setInput(0); setCurrentOperator(null); setResult(null); setTempInput(null); setTempOperator(null); } } return ( <View style={\{flex:1, width:250, justifyContent:"center"}\}> <Text>input:{input}</Text> <Text>currentOperator:{currentOperator}</Text> <Text>result:{result}</Text> <Text>tempInput:{tempInput}</Text> <Text>tempOpertor:{tempOpertor}</Text> {/* 결과 */} <InputContainer> <Text style={\{color:"white", fontSize:35, textAlign:"right"}\}>{input}</Text> </InputContainer> {/* [AC ~ /] */} [ ...생략 ] </View> ) }
- 리팩토링 후 코드 외부에서 필요한 변수와 함수들만 return해준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
//use-calculator.js export const useCalculator = () =>{ const [input,setInput] = useState(0); [ ...생략 ] const onPressReset = ()=>{ if(hasInput){ setInput(0); }else{ setInput(0); setCurrentOperator(null); setResult(null); setTempInput(null); setTempOperator(null); } } return{ input, currentOperator, result, tempInput, tempOpertor, hasInput, onPressNum, onPressOperator, onPressReset, }; };
커스텀 Hook인 useCalculator를 가져와서 구조분해할당하여 사용하면된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
//Calculator.js import { useCalculator } from './use-calculator'; export default () => { const { input, currentOperator, result, tempInput, tempOpertor, hasInput, onPressNum, onPressOperator, onPressReset, } = useCalculator(); return ( <View style={\{flex:1, width:250, justifyContent:"center"}\}> <ButtonContainer> [ ...생략 ] </ButtonContainer> </View> ) }