0

I am trying to convert the JavaScript sample code in ReactJS.

The compiler doesn't display any error but browser is throwing an error at runtime.

I am using this example, please see below.

https://codepen.io/kathykato/pen/prEmKe

I expect to see it workable as displays in above example but I am getting small errors.

What I have tried so far is given below

-------------------------Carousel.js--------------------------


import React, { useState, useEffect } from "react";
import './Carousel.scss'
   
const Carousel = () => {   

  const items = document.querySelectorAll('img');
   const itemCount = items.length;
   const nextItem = document.querySelector('.next');
   const previousItem = document.querySelector('.previous');
   let count = 0;
   
   // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    nextItem.addEventListener('click', showNextItem);
    previousItem.addEventListener('click', showPreviousItem);
    document.addEventListener('keydown', keyPress);
   
    // clean up
    return () => {
    nextItem.removeEventListener('click', showNextItem);
    previousItem.removeEventListener('click', showPreviousItem);
    document.removeEventListener('keydown', keyPress);
  };
})

   function showNextItem() {
     items[count].classList.remove('active');
   
     if(count < itemCount - 1) {
       count++;
     } else {
       count = 0;
     }
   
     items[count].classList.add('active');
     console.log(count);
   }
   
   function showPreviousItem() {
     items[count].classList.remove('active');
   
     if(count > 0) {
       count--;
     } else {
       count = itemCount - 1;
     }
   
     items[count].classList.add('active');
     console.log(count);
   }
   
   function keyPress(e) {
     e = e || window.event;
     
     if (e.keyCode == '37') {
       showPreviousItem();
     } else if (e.keyCode == '39') {
       showNextItem();
     }
   }
   
  //  nextItem.addEventListener('click', showNextItem);
  //  previousItem.addEventListener('click', showPreviousItem);
  //  document.addEventListener('keydown', keyPress);
  

  return (
   <div className="container">
  <div className="slider">
    <img className="active" src="https://source.unsplash.com/gKk9rpyDryU" alt="Nothing " />
    <img src="https://source.unsplash.com/VFGEhLznjPU"  alt="Nothing"/>
    <img src="https://source.unsplash.com/InR-EhiO_js"  alt="Nothing"/>
  </div>
  <nav className="slider-nav">
    <ul>
      <li className="arrow">
        <button className="previous">
          <span>
            <i className="ion-arrow-left-c"></i>
          </span>
        </button>
      </li>
      <li className="arrow">
        <button className="next">
          <span>
            <i className="ion-arrow-right-c"></i>
          </span>
        </button>
      </li>
    </ul>
  </nav>
</div>
 ); 
  }

  export default Carousel;


Application built with
{
  "react": "16.13.0", 
  "react-dom": "^16.13.0", 
  "react-redux": "^7.2.0",
  "redux": "^4.0.4"
  "@material-ui/core": "^4.9.5"
}

Now see the errors below:

TypeError: Cannot read property 'addEventListener' of null
(anonymous function)
H:/ReactJs/Source Codes/react-master/react-master/src/components/Sliders/Carousel.js:14
  11 |  
  12 |  // Similar to componentDidMount and componentDidUpdate:
  13 | useEffect(() => {
> 14 |   nextItem.addEventListener('click', showNextItem);
     | ^  15 |   previousItem.addEventListener('click', showPreviousItem);
  16 |   document.addEventListener('keydown', keyPress);
  17 |  
View compiled
commitHookEffectListMount
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:19731
  19728 | if ((effect.tag & tag) === tag) {
  19729 |   // Mount
  19730 |   var create = effect.create;
> 19731 |   effect.destroy = create();
        | ^  19732 | 
  19733 |   {
  19734 |     var destroy = effect.destroy;
View compiled
commitPassiveHookEffects
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:19769
  19766 |       // before calling any create functions. The current approach only serializes
  19767 |       // these for a single fiber.
  19768 |       commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork);
> 19769 |       commitHookEffectListMount(Passive$1 | HasEffect, finishedWork);
        | ^  19770 |       break;
  19771 |     }
  19772 | }
View compiled
HTMLUnknownElement.callCallback
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:188
  185 |     window.event = windowEvent;
  186 |   }
  187 | 
> 188 |   func.apply(context, funcArgs);
      | ^  189 |   didError = false;
  190 | } // Create a global error event handler. We use this to capture the value
  191 | // that was thrown. It's possible that this error handler will fire more
View compiled
invokeGuardedCallbackDev
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:237
  234 | // errors, it will trigger our global error handler.
  235 | 
  236 | evt.initEvent(evtType, false, false);
> 237 | fakeNode.dispatchEvent(evt);
      | ^  238 | 
  239 | if (windowEventDescriptor) {
  240 |   Object.defineProperty(window, 'event', windowEventDescriptor);
View compiled
invokeGuardedCallback
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:292
  289 | function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
  290 |   hasError = false;
  291 |   caughtError = null;
> 292 |   invokeGuardedCallbackImpl$1.apply(reporter, arguments);
  293 | }
  294 | /**
  295 |  * Same as invokeGuardedCallback, but instead of returning an error, it stores
View compiled
flushPassiveEffectsImpl
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:22853
  22850 | while (_effect2 !== null) {
  22851 |   {
  22852 |     setCurrentFiber(_effect2);
> 22853 |     invokeGuardedCallback(null, commitPassiveHookEffects, null, _effect2);
        | ^  22854 | 
  22855 |     if (hasCaughtError()) {
  22856 |       if (!(_effect2 !== null)) {
View compiled
unstable_runWithPriority
H:/ReactJs/Source Codes/react-master/react-master/node_modules/scheduler/cjs/scheduler.development.js:653
  650 | currentPriorityLevel = priorityLevel;
  651 | 
  652 | try {
> 653 |   return eventHandler();
      | ^  654 | } finally {
  655 |   currentPriorityLevel = previousPriorityLevel;
  656 | }
View compiled
runWithPriority$1
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:11039
  11036 | 
  11037 | function runWithPriority$1(reactPriorityLevel, fn) {
  11038 |   var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel);
> 11039 |   return Scheduler_runWithPriority(priorityLevel, fn);
  11040 | }
  11041 | function scheduleCallback(reactPriorityLevel, callback, options) {
  11042 |   var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel);
View compiled
flushPassiveEffects
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:22820
  22817 |   if (pendingPassiveEffectsRenderPriority !== NoPriority) {
  22818 |     var priorityLevel = pendingPassiveEffectsRenderPriority > NormalPriority ? NormalPriority : pendingPassiveEffectsRenderPriority;
  22819 |     pendingPassiveEffectsRenderPriority = NoPriority;
> 22820 |     return runWithPriority$1(priorityLevel, flushPassiveEffectsImpl);
  22821 |   }
  22822 | }
  22823 | 
View compiled
(anonymous function)
H:/ReactJs/Source Codes/react-master/react-master/node_modules/react-dom/cjs/react-dom.development.js:22699
  22696 | if (!rootDoesHavePassiveEffects) {
  22697 |   rootDoesHavePassiveEffects = true;
  22698 |   scheduleCallback(NormalPriority, function () {
> 22699 |     flushPassiveEffects();
        | ^  22700 |     return null;
  22701 |   });
  22702 | }
View compiled
workLoop
H:/ReactJs/Source Codes/react-master/node_modules/scheduler/cjs/scheduler.development.js:597
  594 | currentPriorityLevel = currentTask.priorityLevel;
  595 | var didUserCallbackTimeout = currentTask.expirationTime <= currentTime;
  596 | markTaskRun(currentTask, currentTime);
> 597 | var continuationCallback = callback(didUserCallbackTimeout);
      | ^  598 | currentTime = exports.unstable_now();
  599 | 
  600 | if (typeof continuationCallback === 'function') {
View compiled
flushWork
H:/ReactJs/Source Codes/react-master/node_modules/scheduler/cjs/scheduler.development.js:552
  549 | try {
  550 |   if (enableProfiling) {
  551 |     try {
> 552 |       return workLoop(hasTimeRemaining, initialTime);
      | ^  553 |     } catch (error) {
  554 |       if (currentTask !== null) {
  555 |         var currentTime = exports.unstable_now();
View compiled
MessagePort.performWorkUntilDeadline
C:/ReactJs/Source Codes/react-master/node_modules/scheduler/cjs/scheduler.development.js:164
  161 | var hasTimeRemaining = true;
  162 | 
  163 | try {
> 164 |   var hasMoreWork = scheduledHostCallback(hasTimeRemaining, currentTime);
      | ^  165 | 
  166 |   if (!hasMoreWork) {
  167 |     isMessageLoopRunning = false;

Thank you

2 Answers 2

1

First, you're using React so prefer using React handlers like the following :

const nextItem = document.querySelector('.next');
nextItem.addEventListener('click', showNextItem);

becomes :

<button className="next" onClick={showNextitem}>
  <span>
     <i className="ion-arrow-right-c"></i>
  </span>
</button>
Sign up to request clarification or add additional context in comments.

2 Comments

Hi Thank you. Do I need to use state ?
You need state if you need the value of a statement in many functions and in your JSX. For example you could put your items in a state yes
1

you need to read some articles about event handling in react.

useEffect needs an empty array as second param to work like componentDidMount.

useEffect(() => {
    document.addEventListener('keydown', keyPress);
   
    // clean up
    return () => {
    document.removeEventListener('keydown', keyPress);
  };
},[])

then as Marc Charpentier has said you add onClick={functionName} to the html element.

The reason that you receive the error is that a functional component does not have lifecycle (unlike class component) and it runs line after line. which means when this line nextItem.addEventListener('click', showNextItem); is executed, the component has not returned any html element and it's not rendered in DOM. it does not exist yet so it's null.

and as you can read from the error message Cannot read property 'addEventListener' of null it can not find addEventListener in null

1 Comment

Hi Thank you. Do I need to use state ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.