I am trying to assign a random value to the "customStyle.top" inside my for loop, but the customStyle.top/customStyle.Left value is not changing randomly. My code is as below:
import React from "react";
const customStyle = {
position: "absolute",
top: "",
left: "",
zIndex: "initial",
color: "green"
};
// Splitting Letters
const SplitText = React.memo(({ str }) => {
return (
<div>
{str.split("").map((item, index) => {
var randLeft = Math.floor(Math.random() * 1000);
var randTop = Math.floor(Math.random() * 600);
let letter = item;
for (let i = 0; i < item; i ) {
customStyle.top = randTop "px";
customStyle.left = randLeft "px";
letter = letter i;
}
console.log(customStyle.top);
return (
<div key={index} style={customStyle}>
{letter}
</div>
);
})}
</div>
);
});
export default SplitText;
link to my CodeSandbox: Click.!
CodePudding user response:
I fixed 2 bugs.
- You are splitting a string at "". So you will only get letters, never a string of multiple letters. That means using a loop here is nonsense!
- In your code you were using a reference to
customStyle
. Anytime you change a value you are changing it everywhere. Therefore copy the value or create a new one. Insert that value in your output.
Code
import React from "react";
// Splitting Letters
const SplitText = React.memo(({ str }) => {
return (
<div>
{str.split("").map((item, index) => {
const style = {
position: "absolute",
top: Math.floor(Math.random() * 600) 'px',
left: Math.floor(Math.random() * 600) 'px',
zIndex: "initial",
color: "green"
};
return (
<div key={index} style={style}>
{item}
</div>
);
})}
</div>
);
});
export default SplitText;
CodePudding user response:
I think you've forgot to add the length
keyword in your for loop
.
Here is working code:
import React from "react";
const customStyle = {
position: "absolute",
top: "",
left: "",
zIndex: "initial",
color: "green"
};
// Splitting Letters
const SplitText = React.memo(({ str }) => {
return (
<div>
{str.split("").map((item, index) => {
var randLeft = Math.floor(Math.random() * 1000);
var randTop = Math.floor(Math.random() * 600);
let letter = item;
for (let i = 0; i < item.length; i ) { // item.length
customStyle.top = randTop "px";
customStyle.left = randLeft "px";
letter = letter i;
}
console.log(customStyle.top);
return (
<div key={index} style={customStyle}>
{letter}
</div>
);
})}
</div>
);
});
CodePudding user response:
If you update a variable inside a component it wont re-render you should use useState
to track all state changes in a functional component, and since you are updating all elements in the loop you will need to use useEffect
as well, this is because the changes will trigger a re-render, and you update again, that re-render and so on, infinite re-renders. The random need to be done only once this using the useEffect
.
import React, { useEffect, useState } from "react";
// Splitting Letters
const SplitText = React.memo(({ str }) => {
const defaultCustomStyle = {
position: "absolute",
top: "",
left: "",
zIndex: "initial",
color: "green"
};
const [customStyles, setCustomStyles] = useState([]);
useEffect(() => {
// Calc here the random values
var randLeft = Math.floor(Math.random() * 1000);
var randTop = Math.floor(Math.random() * 600);
const auxCustomStyle = { ...defaultCustomStyle };
for (let i = 0; i < str.split(""); i ) {
auxCustomStyle.top = randTop "px";
auxCustomStyle.left = randLeft "px";
}
setCustomStyles((prevCustomStyles) => {
prevCustomStyles.push(auxCustomStyle);
return prevCustomStyles;
});
}, []);
return (
<div>
{str.split("").map((item, index) => {
let letter = item;
for (let i = 0; i < item; i ) {
letter = letter i;
}
return (
<div key={index} style={customStyles[index]}>
{letter}
</div>
);
})}
</div>
);
});
export default SplitText;
Check if this works for you.