Trouble with my calculator variable in the Javascript Calculator

Tell us what’s happening:

I have defined const calculator = document.querySelector(‘.calculator’).

I am using react locally to create my javascript calculator and unfortunately, this is failing to compile because the variable that I have described above is throwing a SyntaxError. I’m not sure where the error is located, and any help that can be offered would be greatly appreciated.

:pray:

Your code so far
Here is my updated repo:

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36.

Challenge: Build a JavaScript Calculator

Link to the challenge:

It looks like you have some knowledge in Vanilla JS and now got into React, so you’re sort of trying to use Vanilla JS DOM manipulation instead of actually using React, which is likely to fail.
You don’t use document.querySelector in React, there’s no need.

If you look at what your app is doing: The render method injects a <div id="calculator"> into the DOM. You’re trying to access that div before it’s rendered. So obviously that won’t work.

Also this: const keys = calculator.querySelector(‘.calculator-keys’)

Instead of grabbing the <div> from the DOM and attaching an event listener after it’s rendered, you do that in the render method:

<div className='calculator-keys' onClick={clickHandler}>

The clickHandler function goes inside the class, above your render method, and it probably looks a little more familiar:

function clickHandler(e){
  // do stuff
}

The “wrong” use of DOM manipulation methods wouldn’t cause a Syntax Error, though. That one might be caused by your single quotes, they look a little funky and not like regular single quotes: '

1 Like

Okay, you’re correct the single quotes were the problem with my SyntaxError which is now fixed.

If I’m correct, you’re saying I need to get rid of the following and replace them both a clickHandler function?

  • const calculator = document.querySelector('.calculator')
  • const keys = calculator.querySelector('.calculator-keys')

I think you need to understand first what React is doing, and why you don’t need document.querySelector.

If you add functionality to your website using Vanilla JS, you first build the HTML/DOM. Then after that, your vanilla script grabs elements from the DOM and attaches event listeners etc.

With React, your render method builds the DOM. You attach event listeners in the moment that you create the elements. If you render a <div> or a <button> and you want an event listener on them, you add an onClick to the element:
<div onClick={doSomethingIfSomeoneClicksThisDiv}></div>


So to answer your question, instead of doing this:

const keys = calculator.querySelector('.calculator-keys')

keys.addEventListener('click'), function(e){
  // do stuff
}

You’re doing this:

function handleCalculatorClick(e){
  // do stuff
}

render(){
  return (
    <div className='calculator-keys' onClick={handleCalculatorClick}></div>
  )
}

Everything @jsdisco said is spot on.

I think it might be helpful to see a bit of an example. This is just one way you could do it, but notice that I have no need to know about the DOM. I simplified your code just to illustrate the point. In situations where you would query the DOM in vanilla JS, in React you just pass a function (handler) to one of the event props on the element. For example “onClick”.

import './App.css';
import React from 'react';
import './calculator.css';

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      input: 0,
      output: this.input,
    }
  }

  const clearPressed = (e) => {
    console.log('clear');
  }

  const equalsPressed = (e) => {
    console.log('equals');
  }
  
  const numberPressed = (num) => {
    console.log(num);
  }

  render() {
  return (
    <div className="calculator" id='calculator'>
    <div className= 'display' id ='display'>
    {this.state.input}
    </div>
    <div className='calculator-keys'>

      <button className= 'box-clear' id ='clear' onClick={clearPressed}>AC</button>
      <button className= 'box-equals' id ='equals' onClick={equalsPressed}>=</button>
      <button className= 'box0' id ='zero' onClick={(e) => numberPressed(0) }>0</button>
    </div>
</div>
  );
}}

export default App;

From there you can handle the state however you need to. I hope that makes it more clear :slight_smile: