Im building a webpage with react and JS, but right now I have this error thats making my counter go in to the fritz. Making the gadget that im building not following the 3000ms time interval consistently. Here is the code.
import React from 'react';
import './portfolio.css';
const rand = (min, max) => Math.floor(Math.random() * (max - min 1) min);
const uniqueRand = (min, max, prev) => {
let next = prev;
while(prev === next) next = rand(min, max);
return next;
}
const combinations = [
{ configuration: 1, roundness: 1 },
{ configuration: 1, roundness: 2 },
{ configuration: 1, roundness: 3 },
{ configuration: 2, roundness: 2 },
{ configuration: 2, roundness: 3 }
];
let prev = 0;
const Portfolio = () => {
const wrapper = document.getElementById("wrapper");
setInterval(() => {
const index = uniqueRand(0, combinations.length - 1, prev),
combination = combinations[index];
wrapper.dataset.configuration = combination.configuration;
wrapper.dataset.roundness = combination.roundness;
prev = index;
}, 3000);
return (
<div className='RO__portfolio' id='portfolio'>
<div className='RO__portfolio-content' data-roundness="1" data-configuration ="1" id='wrapper'>
<div className='RO__portfolio-content_shape'></div>
<div className='RO__portfolio-content_shape'></div>
<div className='RO__portfolio-content_shape'></div>
<div className='RO__portfolio-content_shape'></div>
<div className='RO__portfolio-content_shape'></div>
<div className='RO__portfolio-content_shape'></div>
<div className='RO__portfolio-content_shape'></div>
</div>
</div>
)
}
export default Portfolio
React marks the error in the line:
wrapper.dataset.configuration = combination.configuration;
wrapper.dataset.roundness = combination.roundness;
I have tried mooving this element outside the Portfolio element, but it's giving me the exact same error. I'm missing whats happening here. I'm new with react
CodePudding user response:
Try to take a step back and think about what your code does.
First, your user navigates to the page, and this function component is called.
Your code looks in the document for the element with the id "wrapper". It doesn't exist yet.
Later on, your function returns some JSX, causing the element with the id "wrapper" to come into existence. Now, "wrapper" exists.
However, since the earlier code ran before "wrapper" exists, it wasn't stored in the variable.
You could solve this from a number of ways; the others have suggested useRef.
CodePudding user response:
I don't know what configuration
and roundness
are supposed to do...
But to change them in the dataset
property of the DOM element every 3 seconds, you need useRef
and useEffect
hooks.
I suggest you read more here.
One is to retain the reference to the DOM element, as others mentionned.
And the second is to retain a refence to the setInterval
to avoid having more than one interval running...
Try the code below:
Have a look at it running on Codesandbox → Open the console!
import React, { useEffect, useRef } from "react";
// import './portfolio.css'; // Commented out because it was not provided on SO
const rand = (min, max) => Math.floor(Math.random() * (max - min 1) min);
const uniqueRand = (min, max, prev) => {
let next = prev;
while (prev === next) next = rand(min, max);
return next;
};
const combinations = [
{ configuration: 1, roundness: 1 },
{ configuration: 1, roundness: 2 },
{ configuration: 1, roundness: 3 },
{ configuration: 2, roundness: 2 },
{ configuration: 2, roundness: 3 }
];
let prev = 0;
const Portfolio = () => {
const wrapperRef = useRef();
const interval = useRef();
useEffect(() => {
let wrapper = wrapperRef.current;
if (interval.current) {
clearInterval(interval.current);
}
interval.current = setInterval(() => {
const index = uniqueRand(0, combinations.length - 1, prev),
combination = combinations[index];
wrapper.dataset.configuration = combination.configuration;
wrapper.dataset.roundness = combination.roundness;
console.log({
configuration: wrapper.dataset.configuration,
roundness: wrapper.dataset.roundness
});
prev = index;
}, 3000);
}, []);
return (
<div className="RO__portfolio" id="portfolio">
<div
className="RO__portfolio-content"
data-roundness="1"
data-configuration="1"
id="wrapper"
ref={wrapperRef}
>
<div className="RO__portfolio-content_shape"></div>
<div className="RO__portfolio-content_shape"></div>
<div className="RO__portfolio-content_shape"></div>
<div className="RO__portfolio-content_shape"></div>
<div className="RO__portfolio-content_shape"></div>
<div className="RO__portfolio-content_shape"></div>
<div className="RO__portfolio-content_shape"></div>
</div>
</div>
);
};
export default Portfolio;
Notice ref={wrapperRef}
to get the DOM reference.