0

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.

crimsonpython24
  • 2,223
  • 2
  • 11
  • 27

1 Answers1

1

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]);
  • Few questions regarding your questions: which part of the code do you mean by "JSX return?" – crimsonpython24 May 30 '21 at 13:14
  • 1
    This answer worked -- I removed the spread attribute *for the first one* and the animation started working. Thank you so much! – crimsonpython24 May 30 '21 at 13:20
  • Oh, amazing! It's "always" fun converting components, so I'm glad this solved it for you! – Christian Helvin May 30 '21 at 13:27
  • For posterity, the JSX return was meant to be where the `` was located. It would look something like this. `return ( loadings.length && )` – Christian Helvin May 30 '21 at 13:29
  • Quick side question: it seems like `onclick={...` happens before I actually clicked the button. Could that be possible? I only want `newLoadings[index] = true;` to be toggled when I clicked the button, but the animation seemed to be activating way too early – crimsonpython24 May 30 '21 at 13:38
  • Since the `useEffect` is now bound to `[loadings]`, it will update anytime that state changes, including when it initializes. What you can do though, is to wrap all of the logic within the `useEffect` in an if statement. That way it wouldn't load unless the button is clicked. – Christian Helvin May 30 '21 at 13:56
  • What would an example of such an if statement be? – crimsonpython24 May 30 '21 at 14:01
  • Without knowing all of the context of your code, I edited my answer to help show what the `if` statement could look like. – Christian Helvin May 31 '21 at 15:56