Quick foreword: If you are rushing new posts, please move on instead of marking this as a duplicate as I really need help. Apologies if I sound harsh but I've been through this too many times.
I am facing trouble converting the following component code into function-based code. Can anyone please help?
class App extends React.Component {
state = {loadings: [],};
enterLoading = index => {
this.setState(({ loadings }) => {
const newLoadings = [...loadings];
newLoadings[index] = true;
return {loadings: newLoadings,};
});
setTimeout(() => {
this.setState(({ loadings }) => {
const newLoadings = [...loadings];
newLoadings[index] = false;
return {loadings: newLoadings,};
});
}, 6000);
};
render() {
const { loadings } = this.state;
return (
<>
<Button loading={loadings[1]} onClick={() => this.enterLoading(1)}>
Click me!
</Button>
</>
);
}
}
ReactDOM.render(<App />, mountNode);
Here's what I tried:
const [loadings, setloadings] = useState([]);
useEffect((index) => {
console.log("here");
const newLoadings = [...loadings];
newLoadings[index] = true;
setloadings(newLoadings);
setTimeout(() => {
const newLoadings = [...loadings];
newLoadings[index] = false;
setloadings(newLoadings);
}, 6000);
}, []);
// blah blah blah
<Button loading={loadings[0]} onClick={() => setloadings(0)}>Log in</Button>
Essentially I bounced between different convert-class-to-funtion tutorials came up with a problem as described in this thread. I then tried to implement my own version -- and it didn't work.
FYI, "here" was printed in the console, and the console didn't throw up any errors -- the button just wouldn't animate.
Many thanks in advance.
My initial though is you’re expecting loadings to be an already initialized array in your return. Have you tried wrapping the JSX return with loadings.length &&
?
The other thought is the useEffect
is slated to happen on initial mount and doesn’t have the context yet of loadings. Maybe changing the context to [loadings] might solve that.
EDIT: to handle conditional logic to keep this from running unless action is taken, you could do:
useEffect((index) => {
if (loadings[index] !== true) {
console.log("here");
const newLoadings = [...loadings];
newLoadings[index] = true;
setloadings(newLoadings);
setTimeout(() => {
const newLoadings = [...loadings];
newLoadings[index] = false;
setloadings(newLoadings);
}, 6000);
}
}, [loadings]);