프론트엔드✏️/개인공부

[react] 계산기/ 무한 리렌더링, 맨 왼쪽의 0 좀 빼줘

당근먹는하니 2023. 3. 6. 18:46
728x90
반응형

무한 리렌더링 발생~~!! 

 

 

  // allTokenPrice 나오면 input2 값 변경
  useEffect(() => {
    if (token2Price) setInput2(allTokenPrice / token2Price[token2.id].usd);
  }, [allTokenPrice, token2Price, handleChangeInput]);

이 의존성 배열에서 token2Price랑 handleChangeInput을 뺐다. 

 

 토큰을 바꾸면(토큰의 가격이 바뀌면) 새로 계산 되어야할 것 같아서 넣어놨었는데, 토큰 라벨을 눌러서 바꾸면 어차피 토큰 가격이 새로 불러와지고 그럼 allTokenPrice도 다시 계산된다. 

 

 

 

3.0 이라고 치려고 하면 0이 입력되지 않는다. 이건 removeZeros 함수 때문인데... 

 

export const removeZeros = (number: number) => {
  if (number < 1) return number;
  const temp = number;
  const newNum = String(temp).replace(/(^0+(?!$))/, "");
  return newNum;
};

 

 맨 앞의 0만 제거하고 싶었다. 

0.0002 이런 건 입력할 수 있게 number < 1 일땐 그냥 number를 return 하게 했는데, 

3.0 3.02 이런 숫자들은 입력할 수가 없돠...

 

 ^ 문자열의 시작을 나타냄

 0+ 0이 한 번 이상 반복되는 문자열 찾기

 $ 문자열의 끝을 나타냄 

 (?!$) 문자열의 끝을 나타내는 $를 제외하고 찾는다. (문자열 끝에 0이 오는 경우는 제외한다)

 

 

근데 removeZeros 함수에서 console.log 찍어보니까 아예 3.0 이런 값이 아니라 들어올 때 부터 3이 들어왔다.

handleChangeInput 에서 들어오는 value도 3이다. 

 

  const handleChangeInput = useCallback((value: number) => {
    console.log("value:::", value);
    setInput(value);
  }, []);

const onChangeInput = (event: ChangeEvent<HTMLInputElement>) => {
    console.log("event.target.value::", event.target.value);
    const value = Number(event.target.value);
    handleChangeInput(value);
  };

여기서 input은 value = {removeZeros(roundNumber(input))} 였다! 

 

Number로 바꾸는 과정에서 문제가 있는건가? 

 

 

 const handleChangeInput = useCallback((value: number) => {
    console.log("value:::", value);
    setInput(removeZeros(value));
  }, []);
  
   const onChangeInput = (event: ChangeEvent<HTMLInputElement>) => {
    console.log("event.target.value::", event.target.value);
    const value = Number(event.target.value);
    handleChangeInput(value);
  };
  
  ...
  
  <input
                  type="number"
                  step="0.0000000001"
                  value={roundNumber(input)}
                  onChange={onChangeInput}
                  className="w-full text-xl bg-transparent text-zinc-200 appearance-none"
                  placeholder="0.0"
                />

근데 removeZeros를 setInput할 때 부터 넣어주니까 갑자기 된다. 

 

여기서 removeZeros 함수를 쓰면 안 써진다... 

 

이젠 앞의 0이 지워지지 않는다 -ㅅ-

 

  const handleChangeInput = useCallback((value: number) => {
    const temp = removeZeros(Number(value));
    setInput(temp);
  }, []);

  const handleChangeInput2 = useCallback((value: number) => {
    const temp = removeZeros(Number(value));
    setInput2(temp);
  }, []);
  
  
  // function.ts
  
  export const removeZeros = (number: number) => {
  if (isNaN(number)) return 0; // 입력값이 숫자가 아니면 0을 반환
  const temp = number;
  const newNum = String(temp).replace(/(^0+(?!$))/, "");
  return Number(newNum);
};

removeZeros에서 return 할 때 string 타입 그대로 내보내길래 Number로 감싸줬다. 

이거랑 딱히 상관은 없나봄,, 

0을 지우려고 해도 안 지워진다 

 

034를 입력했을 땐데 여기선 분명 34인데? 

 

뭘까 왜 보이는 것만 03.4로 보이는 거지? 

 

새로고침하니까 갑자기 된다 엥ㅎ 

 

근데 그냥 3이라고만 썼는데 저렇게 쭈루루룩 붙어버림!!! 

 

 const handleChangeInput = useCallback((value: number) => {
    const temp = removeZeros(Number(value));
    console.log("removeZeros 후:", temp);
    setInput(roundNumber(temp));
  }, []);

여기서 roundNumber(temp)로 setInput 해주면서... 이렇게 된 것 같다. 

 

export const roundNumber = (number: number) => {
  if (Number.isInteger(number)) return number;
  const temp = number;
  return Math.round(temp * 10000000000) / 10000000000;
};

roundNumber에 Number.isInteger() 를 추가해줬다 ㅎㅎ; 이렇게 막는 게 맞나...

 

아닌가봐... 3을 치면 2.9999996 머 이런식으로 나온다. 

이유를 알 수 없지만 일단 다시 value = {roundNumber(input)} 이렇게 써줬다. 

 

앞의 0은 아직도 제거 못 하고 있다!!!!!!!!!! 

useState에 대한 이해가 부족한건가 

 

 

--------3월 9일 추가

 

 <input
                  type="number"
                  value={roundNumber(input).toString()}
                  onChange={onChangeInput}
                  className="w-full text-xl bg-transparent text-zinc-200 appearance-none"
                />

뒤에 toString()을 붙이니 앞에 0이 붙는 문제가 해결됐다.

 

value에 직접 숫자를 할당하면 HTML 표준에 따라 앞에 0이 붙을 수 있다는데 ,,, 

일단 string으로 변환해서 할당해주는 것으로 문제가 해결됐다. 

728x90
반응형