I am trying to create a home page carousel. It is basically 3 divs with articles and I want to be able to manipulate certain things, like the title's font size and placement (with margin top)
My initial code was like this:
const Home = () => {
const [margin, setMargin] = useState('420px')
const [font, setFont] = useState('20px')
function mouseOver (){
setMargin('320px')
setFont('40px')
}
function mouseOut(){
setMargin('420px')
setFont('20px')
}
return(
<div className='carousel'>
<div className='column' id='column1' onMouseOver={mouseOver} onMouseOut={mouseOut}>
<p className='title' id='title1' style={{marginTop: margin,fontSize: font ,color:'black'}} > Τitle 1 </p>
<p className='markdown' id='markdown1'>mark1 </p>
</div>
<div className='column' id='column2' onMouseOver={mouseOver} onMouseOut={mouseOut}>
<p className='title' id='title2' > Τitle 2</p>
<p className='markdown' id='markdown2'> mark2</p>
</div>
<div className='column' id='column3'>
<p className='title' id='title3' onMouseOver={mouseOver} onMouseOut={mouseOut}> Τitle 3 </p>
<p className='markdown' id='markdown3'> mark3</p>
</div>
</div>
)
}
export default Home;
Every time I hovered over any of the titles, the size of all of them changed because I use the same value and change it in each and every one of them. So I wanted to do it in a more of a react way, cause this just seemed to me like plane html with some react, so here is what I came up with.
const Home = () => {
const [margin, setMargin] = useState('420px')
const [font, setFont] = useState('20px')
function mouseOver(){
setMargin('320px')
setFont('40px')
}
function mouseOut(){
setMargin('420px')
setFont('20px')
}
const arrayDivs =[]
for (let i=0; i<=2; i++) {
const div = React.createElement(
'div', //type
{key: i, className: 'column', id: `column${i+1}` }, //properties of element
React.createElement(
'p', //children of element
{
key: i,
className: 'title',
id: `title${i+1}`,
style: {
marginTop: margin,
fontSize: font
},
onMouseOver: mouseOver(),
onMouseOut:mouseOut()
}
),
`title${i+1}`
)
arrayDivs.push(div)
}
return(
<div className='carousel'>
{ arrayDivs }
</div>
)
}
export default Home;
But I run in to this error:
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
at renderWithHooks (react-dom.development.js:16317:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27451:1)
at performUnitOfWork (react-dom.development.js:26557:1)
at workLoopSync (react-dom.development.js:26466:1)
at renderRootSync (react-dom.development.js:26434:1)
The code is render looping because it is immediately invoking the handlers:
for (let i=0; i<=2; i++){
const div = React.createElement(
'div', // type
{ key: i, className: 'column', id: `column${i+1}` }, // properties of element
React.createElement(
'p', // children of element
{
key: i,
className: 'title',
id: `title${i+1}`,
style: { marginTop: margin, fontSize: font },
onMouseOver: mouseOver(), // <-- immediately invoked
onMouseOut: mouseOut() // <-- immediately invoked
}
),
`title${i+1}`
);
arrayDivs.push(div);
}
You will want to instead pass a reference to the mouseOver
and mouseOut
handlers:
{
key: i,
className: 'title',
id: `title${i+1}`,
style: { marginTop: margin, fontSize: font },
onMouseOver: mouseOver, // <-- pass reference
onMouseOut: mouseOut // <-- pass reference
}
This being said, using the onMouseOver
and onMouseOut
handlers tend to not work that well in practice. Whether or not it's considered the "React Way" I highly recommend using CSS and a :hover
rule to apply the CSS styling.
Example:
CSS
.column .title {
margin-top: 420px;
font-size: 20px;
}
.column:hover .title {
margin-top: 320px;
font-size: 40px;
}
.title {
color: black;
}
Home
const Home = () => {
return(
<div className='carousel'>
<div className='column' id='column1'>
<p className='title' id='title1'>Τitle 1</p>
<p className='markdown' id='markdown1'>mark1</p>
</div>
<div className='column' id='column2'>
<p className='title' id='title2'>Τitle 2</p>
<p className='markdown' id='markdown2'>mark2</p>
</div>
<div className='column' id='column3'>
<p className='title' id='title3'>Τitle 3</p>
<p className='markdown' id='markdown3'>mark3</p>
</div>
</div>
)
}