#reactjs
#reactjs
Вопрос:
Я пытаюсь преобразовать пример кода JavaScript в ReactJS.
Компилятор не отображает никаких ошибок, но браузер выдает ошибку во время выполнения.
Я использую этот пример, пожалуйста, смотрите ниже.
https://codepen.io/kathykato/pen/prEmKe
Я ожидаю, что он будет работать, как показано в приведенном выше примере, но я получаю небольшие ошибки.
То, что я пробовал до сих пор, приведено ниже
-------------------------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"
}
Теперь посмотрите на ошибки ниже:
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 amp; 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;
Спасибо
Ответ №1:
Во-первых, вы используете React, поэтому предпочитаете использовать обработчики React, подобные следующим :
const nextItem = document.querySelector('.next');
nextItem.addEventListener('click', showNextItem);
становится :
<button className="next" onClick={showNextitem}>
<span>
<i className="ion-arrow-right-c"></i>
</span>
</button>
Комментарии:
1. Привет, спасибо. Нужно ли мне использовать состояние?
2. Вам нужно указать, если вам нужно значение оператора во многих функциях и в вашем JSX. Например, вы могли бы перевести свой
items
в состояние yes
Ответ №2:
вам нужно прочитать несколько статей об обработке событий в react.
useEffect
для работы требуется пустой массив в качестве второго параметра componentDidMount
.
useEffect(() => {
document.addEventListener('keydown', keyPress);
// clean up
return () => {
document.removeEventListener('keydown', keyPress);
};
},[])
затем, как сказал Марк Шарпантье, вы добавляете onClick={functionName}
в html-элемент.
Причина, по которой вы получаете ошибку, заключается в том, что функциональный компонент не имеет жизненного цикла (в отличие от компонента класса) и выполняется строка за строкой. это означает, что при выполнении этой строки nextItem.addEventListener('click', showNextItem);
компонент не вернул ни одного элемента html и он не отображается DOM
. его еще не существует, так что это null
.
и, как вы можете прочитать из сообщения об ошибке Cannot read property 'addEventListener' of null
, он не может найти addEventListener
в null
Комментарии:
1. Привет, спасибо. Нужно ли мне использовать состояние?