React에서 처음부터 계산기 만들기

소개



글쎄요, 처음부터 계산기를 만든다고 말하는 것은 React와 같은 라이브러리로 작업할 때 과장입니다. 여기서 내가 정말로 의미하는 바는 이 프로젝트를 구축하는 동안 내 의도는 내 자신의 계산 알고리즘을 만드는 것이었기 때문에 나중에 내 앱 내부 작동의 일부로 구현할 수 있다는 것입니다. 그리고 나는 했다! 여기있어.

이것은 React에서 계산기를 구축하기 위한 안내서가 결코 아님을 명심하십시오. 이 전체 기사는 단순히 내 경험, 그 과정에서 발견한 문제 및 이를 해결하기 위해 생각해 낸 솔루션을 문서화하는 방법입니다.

목차


  • Overview of the challenge

  • The process
  • Challenge N° 1
  • Challenge N° 2
  • Challenge N° 3

  • Features left to add and issues left to solve
  • And it's done!
  • Where to find me...

  • 챌린지 개요



    원래 챌린지는 Frontend Mentor 에서 찾을 수 있습니다. 요약하자면, Frontend Mentor의 직원들은 세 가지 테마를 번갈아 사용할 수 있는 레이아웃으로 기본 작업을 수행하는 계산기를 만들고 그 위에 반응형으로 만들도록 합니다. 사용자가 선호하는 테마 색 구성표를 설정하도록 허용하려는 경우에도 보너스 챌린지가 있습니다.

    저는 원래 몇 달 전에 계산기 알고리즘을 구축했습니다. 난수 배열을 입력으로 사용하여 함수 중 하나를 호출할 때마다 기본 계산(더하기, 빼기, 나누기, 곱하기, 지수 및 계승)을 수행할 수 있는 일련의 함수였습니다. 계승 함수는 예외입니다. 그래서, 다음과 같은 것:

    // Takes the first number and calculates it's power to the rest of the numbers inputed.
    const power = (...numbers) => {
      // Takes the first number off the list and stores it in a new variable.
      const firstNumber = numbers.splice(0, 1);
      let multiplyTheRest = 1;
      let result = 1;
      // Takes the numbers array and multiplies each one times the next.
      for (let i = 0; i < numbers.length; i++) {
        multiplyTheRest *= numbers[i];
      }
      // Multiplies the first number inside firstNumber by itself as many times whatever value was outputed in the previous loop.
      for (let i = 1; i <= multiplyTheRest; i++) {
        result *= firstNumber;
      }
      return result;
    };
    


    나는 일주일 전에 먼지를 모으는 이 오래된 저장소를 발견했고, 그때 배운 것을 내 손으로 사용하기 위해 도전하기로 결정했습니다. 따라서 최종 제품이 챌린지의 프롬프트와 정확히 일치하지 않거나 작동하지 않는 이유는 무엇입니까? 그리고 이러한 기능이 React 상태와 그에 대한 현재 지식과 함께 작동하도록 하기 위해 몇 가지를 변경해야 했지만 대부분의 기능을 원래 그대로 유지했습니다.

    과정



    과제 번호 1: 그리드를 만드는 것은 내가 원하는 모든 것을 배치하고... 그리고 비참하게 실패합니다.

    I'm not going to lie. This one was kind of a though one in the visual area. Not because it was particularly difficult to style in Sass, but because after making two functions that build and returned all my buttons, I was left with an unordered grid of 20 elements (some of them bigger than the rest.)

    My first idea to make the keypad resemble the one of an actual calculator was to use the grid-template-area property on my parent element, and then give each group of related children the same grid-area name. This turned out a failure no matter how I wrote the template. Many of my buttons always ended up either overflowing or outright disappearing from the grid, and I ended up spending the biggest chunk of time just to try and make it work, then ditching it for something else, and then going back to it again.

    Lucky for me, around this time Kevin Powell had published a . It was unrelated to what I was trying to accomplish, but it introduced me to the grid-column and grid-row properties which, alongside the addition of a data attribute to every single one of my buttons, helped me to finally get that annoying grid exactly the way I wanted.

    Basically, I set the display of my parent element to grid, set my number of columns with grid-template-columns , and then I used a combination of those two properties I learned and span to put my problematic keys in their place, selecting them by their data-key attribute.

    .Buttons__button[data-key="="] {
                grid-row: 5;
                grid-column: 2/5;
            }
    

    챌린지 N° 2: 계산기를 실제로 작동하게 만드는 것... 그리고 실제로 몇 시간 만에 완료하는 것!

    As I previously mentioned, I already had a very basic calculation algorithm lying around my repositories, so I only had to figure out how to implement it in the app with the usestate hook.

    The first problem was choosing what type of input to pass into the function I was supposed to code.

    I needed to use the calc state prop not only to store my input, but also to display what the user was inputting. So I decided to go with a string, because it was easier to manipulate inside the state, and also, because I'm yet to figure out a non-convoluted way to set my state to an array of numbers interleaved with string values. Who knows, maybe I'm not seeing it, but it would be a hundred times easier to work with.

    The next problem I came across was getting each of those string values into an array without having multiple digit numbers breaking up and operators getting out of place.

    I solved this by taking the string input and, in one hand, filtering the operators out, and in the other hand, splitting it by its operators to get the numbers out. I stored each of the two resulting arrays into their own variable, and proceeded to combine both into const operations using map. Finally, I mapped the result again to obtain the final array newArray (yes, I ran out of names by this point) with parsed numbers, filtering any undesired values at the end. I hope this snippet speaks a little better about it:

    const operators = ["+", "-", "/", "*", "^", "!"];
    const numbers = nums.split(/[+-\/*^!]/)
    const opts = [...nums].filter( value => operators.includes(value))
    
    const operation = numbers.map( (num, i) => {
        if(opts[i] !== undefined) {
          return [num, opts[i]]
        } else {
          return num
        }
        }).flat().filter( value => value !== "");
    
    const newArray = operation.map( (value, i, array )=> {
        if(!(operators.includes(value))) {
            return parseFloat(value);
        } else if ( value === array[i-1] && value === "-") {
            return parseFloat(value+array[i+1])
        } else {
            return value;
        }
      }).filter( (value, i, array) => {
        if((typeof(value) === "number" && typeof(array[i-1]) === "string") || array[i-1] === undefined || typeof value === "string") {
            return value;
        }
      })
    

    This piece of code basically turns this: "2+2--222"
    Into this: [2, "+", 2, "-", -222]

    From that point on, I just had to make a loop with newArray.length > 0 as a condition to take each of its values and perform a calculation with the next one.

    Now the algorithm was ready to be used.

    챌린지 3번: 버튼이 성가신 소리를 재생하게 하기. 자존심을 삼키고 라이브러리를 사용하면 실제로 매우 쉽습니다.

    This was the easiest problem of the bunch once I stopped trying to make it happen with vanilla JS and installed Howler .

    앱 내에서 사운드를 재생하려면 콘솔을 열고 npm -i howler를 실행하고 holw 개체 생성자를 가져온 다음 사운드 소스를 매개 변수로 사용하는 함수를 만들고 새 하울을 인스턴스화하면 됩니다. 로컬 변수 내부에 두 개의 키-값 쌍이 있는 객체를 만든 다음 play() 메서드를 여기에 적용합니다.

    const playSound = (src) => {
        const sound = new Howl ({
          src,
          html5: true,
        })
    
        sound.play()
      }
    


    이를 통해 앱을 배포할 준비가 되었습니다.

    추가해야 할 기능과 해결해야 할 문제가 남아 있습니다.



    사용자가 긴 연산을 입력하고 그 연산이 그 내부 어딘가에 지수 계산을 포함하는 경우 알고리즘의 계산 프로세스에는 여전히 몇 가지 문제가 있습니다. 이것은 알고리즘에 연산 우선 순위를 구현하면 확실히 해결될 것이고 이미 방법을 생각했지만 지금은 미래에 처리하기로 결정합니다. 그 외에도 사운드 및 테마 토글러와 같은 기타 기능이 추가되었습니다. 또한 약간의 리팩토링 및 성능 최적화.

    이 프로젝트로 돌아오면 이에 대해 업데이트하겠습니다.

    그리고 완료되었습니다!

    You can find my solution to this challenge in its repository . 당신도 그것을 시도 할 수 있습니다 live!



    나를 찾는 곳...

    You can find me on GitHub 및 , 나는 때때로 초보자 개발자로서의 경험을 공유합니다.

    좋은 웹페이지 즐겨찾기