1

I'm making a nodejs app using react for some reason when I run yarn start I get this error "TypeError: btn_bmi.addEventListener is not a function". Anyone have any ideas why this would be setting it up like this has worked for me in the past I'm unsure what is causing the error?

import React from 'react';


var btn_bmi = document.getElementsByClassName('bmi_button');
     btn_bmi.addEventListener('click', calculate_bmi());

    function calculate_bmi() {
        let Weight = document.getElementsByClassName('bmi_weight').value;
        let Height = document.getElementsByClassName('bmi_height').value;
        let Age = document.getElementsByClassName('bmi_age').value;
        let Test = document.getElementsByClassName('test_print');
        let bmi_calc = Weight / Height / Height * 10000;
        let bmr_calc = 88.2 + (13.362 + Weight) + (4.799 + Height) - (5.677 + Age);

        //if nothing entered show error
        if (Weight, Height, Age == 0){
            alert("Please enter your Height, Weight and Age so we can achieve your goals!")
            }
            else{
            //
            Test.innerHTML = document.write= bmi_calc + bmr_calc;
            }

    }

function setup_page () {
    return (
    <div className='setup_main'>
     <input className= 'bmi_weight' type='number' placeholder='Weight in kg:'></input>
     <input className= 'bmi_height' type='number' placeholder='Height in cm:'></input>
     <input className= 'bmi_age' type='number' placeholder='Age:'></input>
     <button className='bmi_button'>calculate</button>
     <p className='test_print'></p>
     </div>
    );
    }

export default setup_page;
lukeet
  • 461
  • 1
  • 4
  • 22
  • 4
    You should not be mixing vanilla JS DOM methods and React code in this way. Try using the React methods and tools instead (onClick instead of addEventListeners, Components instead of using innerHTML, etc.) This code needs some heavy refactoring. The TypeError you are getting should be your least concern IMHO. – Kostas Minaidis Feb 24 '20 at 22:29
  • Does this answer your question? [What do querySelectorAll and getElementsBy\* methods return?](https://stackoverflow.com/questions/10693845/what-do-queryselectorall-and-getelementsby-methods-return) – Heretic Monkey Feb 24 '20 at 22:31
  • I'm really new to react so am trying to draw on my previous experience with javascript but it's obviously not the correct implementation – lukeet Feb 24 '20 at 23:00
  • `var btn_bmi = document.getElementsByClassName('bmi_button');` returns an `HTMLCollection` object (an array-like object) that does NOT have a `.addEventListener()` method. You have to get one or more items from the collection and call `.addEventListener()` on each one you want to or use a differernt method such as `document.querySelector()` that only returns a single DOM element. – jfriend00 Feb 25 '20 at 00:22

3 Answers3

4

document.getElementsByClassName(...) returns an HTMLCollection, not a single HTML element. That's because you can have multiple elements with the same class name.

If you want to assume only one comes back, replace with:

var btn_bmi = document.getElementsByClassName('bmi_button')[0];

Or, IMO the cleaner:

const btn_bmi = document.querySelector('.bmi_button');

But really, the best thing for you to do is to place the event listener in the JSX; that way, the event attachment/detachment is taken care of for you when React outputs the DOM and re-renders:

<button className='bmi_button' onClick={calculate_bmi}>calculate</button>
Jacob
  • 77,566
  • 24
  • 149
  • 228
0

React creates virtual DOM which cannot be accessed by document.querySelector and other similar functions. If you wish to access something created by react you must use this if you are using class component or hook useRef() if you are using function components(the name can be something else but I mean those: const MyComponent = props => ( <some-element />)). For your purpose you should create a form which holds its values in a state (either this.state or useState() hook)
EDIT
Below answer is quite right too but if you are using React to render your html the result of document.getElementsByClassname will return empty collection

TZiebura
  • 494
  • 3
  • 15
  • thank you very much I am new to react an nodejs although have some experience with javascript and html, so this is new to me hahah – lukeet Feb 24 '20 at 22:35
0

Also if (Weight, Height, Age == 0){ probably doesn't do what you think it does.