Re initialize component in React

I have a component in React named QuestBox. I have a CSS class which runs an animation - enter . What I wanted to do is whenever a button named Next inside the QuestBox is clicked, I want the QuestBox component to re-initialize so that it can show the ‘enter’ animation.

The render method of QuestBox

   render(){
        let {question, options, answer}= this.props.data;
        let rads = options.map((e,i)=>{
            let active;
            if(this.state.active)
            {
                if(e == answer)
                    active = "green";
                else
                    active = "red";
            }
            
            return<Radio key={i} value={e} active={active} name='questionValue' onChange={e=>{this.changeIndex(i)}} checked={this.state.selected == i}/>
        })
        return (
            <div key={this.state.key} className={`${cx({exit: this.state.exit}, {enter: !this.state.exit}, 'questionBox')}`}>
                <div>{question}</div>
                <div id="options">
                    {rads}
                </div>
                <div>
                    <Button value="Check your answer" onClick={this.checkAns}/>
                    <Button value="Next" disabled={!this.state.answered} onClick={this.handleNext}/>
                </div>
            </div>
        )
    }

I don’t know how to proceed further.

@sauravk7077

so you want the animation to happen every time you hit next?

can you put a link to the code on codepen so i can test some out? i dont know what your css looks like or anything, it would be a big help

@keyframes exit{
    0%{
        opacity: 1;
        width: 100%;
    }
    100%{
        opacity: 0;
        width: 0;
    }
}

@keyframes enter{
    0%{
        opacity: 0;
        width: 60%;
    }
    100%{
        opacity: 1;
        width: 100%;
    }
}

so you want it to fade out then fade in again for the next one? your probably better off doing this without keyframes if your using react mate, you could use style binding or class binding which probably be better, or even easier just use something like animate.css, i will add react solution in a min.

const fadeIn = {
  opacity: "1",
  width: "100%",
};

const fadeOut = {
  opacity: "0",
  width: "60%",
};

class App extends Component {
  constructor() {
    super();
    this.state = {
      show: true,
    };
  }

  handleFade() {
    this.setState({ show: !this.state.show });
  }
  render() {
    return (
      <div className="App">
        <div className="box" style={this.state.show ? fadeIn : fadeOut}></div>

        <button onClick={this.handleFade.bind(this)}>toggle fade</button>
      </div>
    );
  }
}

//css

.box {
  width: 400px;
  height: 400px;
  background: red;
  transition: .5s ease;
}


of if you want to fade out then fade back in

const fadeIn = {
  opacity: "1",
  width: "100%",
};

const fadeOut = {
  opacity: "0",
  width: "60%",
};

const fadeTime = 1000;

class App extends Component {
  constructor() {
    super();
    this.state = {
      show: true,
    };
  }

  fadeOutIn() {
    this.handleFade()
    setTimeout(() => {
      this.handleFade()
    }, fadeTime)
  }

  handleFade() {
    this.setState({ show: !this.state.show });
  }
  render() {
    return (
      <div className="App">
        <div className="box" style={this.state.show ? fadeIn : fadeOut}></div>

        <button onClick={this.fadeOutIn.bind(this)}>toggle fade</button>
      </div>
    );
  }
}

@sauravk7077

i made an example for you for a toggle fade, so not you can just fade in and fade out your animation as you like mate, remember to add a transition to you css class like mine is to make it smooth

It is not working.
Check out the code at my github page Quiz Machine
Well the design isn’t ready and my code is a mess.

@sauravk7077 ok i will have a look now that i have your code, much easier to work with thanks

heres the full Questbox component i think this is what you want aint it?

import React from "react";
import Button from "./Button";
import Radio from "./Radio";

const fadeIn = {
  opacity: "1",
  width: "100%",
};

const fadeOut = {
  opacity: "0",
  width: "60%",
};

const fadeTime = 1000;
class QuestBox extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 0,
      active: false,
      answered: false,
      show: true,
      key: Math.random(),
    };
  }
  checkAns = (e) => {
    if (!this.state.answered) {
      this.setState({
        active: true,
        answered: true,
      });
      console.log(this.state);
      if (
        this.props.data.answer == this.props.data.options[this.state.selected]
      )
        this.props.addPoints();
    }
  };

  fadeOutIn() {
    this.handleFade();
    setTimeout(() => {
      this.handleFade();
    }, fadeTime);
  }

  handleNext = (e) => {
    this.setState({
      enter: false,
      key: Math.random(),
    });
    this.props.onClick();
  };

  handleFade() {
    this.setState({ show: !this.state.show });
  }

  changeIndex = (i) => {
    this.setState({
      selected: i,
    });
  };

  render() {
    let { question, options, answer } = this.props.data;
    let rads = options.map((e, i) => {
      let active;
      if (this.state.active) {
        if (e == answer) active = "green";
        else active = "red";
      }

      return (
        <Radio
          key={i}
          value={e}
          active={active}
          name="questionValue"
          onChange={(e) => {
            this.changeIndex(i);
          }}
          checked={this.state.selected == i}
        />
      );
    });
    return (
      <div
        className="questionBox"
        style={this.state.show ? fadeIn : fadeOut}
        key={this.state.key}
      >
        <div>{question}</div>
        <div id="options">{rads}</div>
        <div>
          <Button value="Check your answer" onClick={this.checkAns} />
          <Button value="Next" onClick={this.fadeOutIn.bind(this)} />
        </div>
      </div>
    );
  }
}

export default QuestBox;
;

Thanks, it works for me.

1 Like

Wait, I forgot about the main problem.

@sauravk7077

whats that mate?

The code is behaving unusual. React Component Content 's method handleCheckAns is not getting executed(It is passed as ‘onClick’ on QuestBox) and the the class name ‘green’ or ‘red’ is to be added only when active boolean (state of QuestBox) is true.

What that means, the radio button’s background color should become red or green on clicking Check your answer button and reset on clicking Next button.

@sauravk7077

can you push you code to your repo and send me the link again and il have a look for you mate, ok i think i get what you mean and first thing i will say is are you passing a prop called onClick? onClick is a reserved word so you shouldnt be using that as prop tbh mate

The repository is same as above.Quiz Machine

@sauravk7077

whats this for mate? key={Math.random()}

this is hard to work out but il get there in the end lol

Well, I though key would allow it to reinitialize the component so, on every next button click, I change it to something random.

no key is a reserved word to use in sort order if you had something like a list so you ya dont wanna be using random on it

What I really wanted to do was whenever the next button is clicked , it would load the next question with transition. BRB

yeah i get what your trying to do, im just trying to work out what some of the stuff does and work my way though components because you code a lot different from me, i can tell your new to this and i was the same when i first started, react is hard to learn passing through components and stuff like that, i see you have functions like forceUpdate and stuff i dont even know where that goes lol

Anyway its 4.33am here in the uk so im gonna have to leave this till tomorrow mate cuz its gonna take a while for me to figure out cuz its more than just a problem of passing a prop through, try sort it out if ya can mate if not i will be back on tommorow and will sort it :slightly_smiling_face: