Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React force componentDidMount

Tags:

reactjs

I have the following:

import React from 'react';
import axios from 'axios';

class FirstName extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            submitted: false
        };
    }
    getName () {
        var name = this.refs.firstName.value;
        this.setState(function() {
          this.props.action(name);
        });
    }
    handleSubmit (e) {
        e.preventDefault();
        this.setState({ submitted: true }, function() {
            this.props.actionID(2);
            this.props.activeNav('color');
        });
    }
    render () {
        return (
            <div>
                <h2>tell us your first name</h2>
                <form>
                    <input 
                        type="text"
                        ref="firstName"
                        onChange={this.getName.bind(this)}
                    />
                    <div className="buttons-wrapper">
                        <button href="#">back</button>
                        <button onClick={this.handleSubmit.bind(this)}>continue</button>
                    </div>
                </form>
            </div>  
        );
    }
};

class PickColor extends React.Component {
    backToPrevious (e) {
        e.preventDefault();
        this.props.actionID(1);
        this.props.activeNav('name');
    }
    goToNext (e) {
        e.preventDefault();
        this.props.actionID(3);
        this.props.activeNav('design');
        this.props.displayIconsHolder(true);
    }
    getColorValue(event) {
        this.props.color(event.target.getAttribute("data-color"));
    }
    render () {
        var colors = ['red', 'purple', 'yellow', 'green', 'blue'],
            colorsLink = [];

        colors.forEach(el => { 
            colorsLink.push(<li 
                                data-color={el} 
                                key={el} 
                                onClick={this.getColorValue.bind(this)} 
                                ref={el}>
                                    {el}
                            </li>
            );
        });

        return (
            <section>
                <ul>
                    {colorsLink}
                </ul>
                <button onClick={this.backToPrevious.bind(this)}>back</button>
                <button onClick={this.goToNext.bind(this)}>continue</button>
            </section>
        );
    }
}

class ConfirmSingleIcon extends React.Component {
    goBack () {
        this.props.goBack();
    }
    confirmCaptionandIcon (event) {
        var optionID = event.target.getAttribute("data-option-id"),
            name = event.target.getAttribute("data-option-name");
        this.props.setOptionID(optionID);
        this.props.setIcon(1, name, optionID, false);
    }
    goNext () {
        this.props.goNext();
    }
    render () {
        console.log(this.props.currentState);
        var options = [],
            that = this;
        this.props.iconOptionsList.forEach(function(el){
            options.push(<li onClick={that.confirmCaptionandIcon.bind(that)} key={el.option} data-option-name={el.option} data-option-id={el.id}>{el.option}</li>);
        });
        return (
            <div>
                <h2>Choose your caption</h2>
                <h3>
                    {this.props.selectedIcon}
                </h3>
                <ul>
                    {options}
                </ul>
                <button onClick={this.goBack.bind(this)} >back</button>
                <button onClick={this.goNext.bind(this)} >confirm</button>
            </div>
        );
    }
}

class ConfirmCaption extends React.Component {
    handleClick () {
        var currentState = this.props.currentState;
        this.props.setIcon(currentState.icon_ID, currentState.selectedIcon, currentState.option_ID, true);
        this.props.setIconVisiblity(true);
        this.props.setIconListVisiblity(false);
    }
    render () {
        console.log(this.props.currentState);
        return (
            <div>
                <p onClick={this.handleClick.bind(this)}>confirm icon and caption</p>
            </div>
        );
    }
}

class ChooseIcon extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            icons: [],
            iconList: true,
            confirmIcon: false,
            confirmCaption: false,
            selectedIconOptions: '',
            icon_ID: '',
            option_ID: '',
            selectedIcon: ''
        };
        this.setOptionID = this.setOptionID.bind(this);

        this.setIconVisiblity = this.setIconVisiblity.bind(this);
        this.setIconListVisiblity = this.setIconListVisiblity.bind(this);
    }
    setOptionID (id) {
        this.setState({ option_ID: id })
    }
    setIconVisiblity (onOff) {
        this.setState({ confirmIcon: onOff })
    }
    setIconListVisiblity (onOff) {
        this.setState({ iconList: onOff })
    }
    componentDidMount() {
        var url = `http://local.tshirt.net/get-options`;
        axios.get(url)
            .then(res => {
                this.setState({ icons:res.data.icons });
        });
    }
    handleClick (event) {
        var iconId = event.target.getAttribute("data-icon-id"),
            that = this;
        this.state.icons.forEach(function(el){
            if(el.id == iconId){
                that.setState(
                    { 
                        confirmIcon: true,
                        iconList: false,
                        selectedIcon: el.name,
                        icon_ID: iconId,
                        selectedIconOptions: el.option
                    }
                );
            }
        });
    }
    goBack () {
        this.setState(
            { 
                confirmIcon: false,
                iconList: true
            }
        );
    }
    goNext () {
        this.setState(
            { 
                confirmIcon: false,
                iconList: false,
                confirmCaption: true
            }
        );
    }
    render () {
        var icons = [];
        this.state.icons.forEach(el => {
            icons.push(<li data-icon-id={el.id} onClick={this.handleClick.bind(this)} key={el.name}>{el.name}</li>);
        });
        return (
            <div>
                {this.state.iconList ? <IconList icons={icons} /> : ''}
                {this.state.confirmIcon ? <ConfirmSingleIcon goBack={this.goBack.bind(this)} 
                                                             goNext={this.goNext.bind(this)} 
                                                             setIcon={this.props.setIcon} 
                                                             selectedIcon={this.state.selectedIcon}
                                                             iconOptionsList ={this.state.selectedIconOptions}
                                                             setOptionID={this.setOptionID}
                                                             currentState={this.state} /> : ''}

                {this.state.confirmCaption ? <ConfirmCaption currentState={this.state} 
                                                             setIcon={this.props.setIcon}
                                                             setIconVisiblity={this.setIconVisiblity}
                                                             setIconListVisiblity={this.setIconListVisiblity}  /> : ''}
            </div>
        );
    }
}

class IconList extends React.Component {
    render () {
        return (
            <div>
                <h2>Pick your icon</h2>
                <ul>
                    {this.props.icons}
                </ul>
            </div>
        );
    }
}

class Forms extends React.Component {
    render () {
        var form;
        switch(this.props.formID) {
            case 1:
                form = <FirstName action={this.props.action} actionID={this.props.switchComponent} activeNav={this.props.activeNav} />
                break;
            case 2:
                form = <PickColor displayIconsHolder={this.props.seticonsHolder} color={this.props.colorVal} actionID={this.props.switchComponent} activeNav={this.props.activeNav} />
                break;
            case 3:
                form = <ChooseIcon setIcon={this.props.setOptionA} />
                break;
        }
        return (
            <section>
                {form}
            </section>
        );
    }
}

export default Forms;

"ChooseIcon" is a component that will get used 3 times therefore everytime I get to it I need to bring its state back as if it was the first time.

Ideally I would need to make this ajax call everytime:

componentDidMount() {
    var url = `http://local.tshirt.net/get-options`;
    axios.get(url)
        .then(res => {
            this.setState({ icons:res.data.icons });
    });
}

is there a way to manually call componentDidMount perhaps from a parent component?

like image 722
Aessandro Avatar asked Nov 29 '22 13:11

Aessandro


2 Answers

React handles component lifecycle through key attribute. For example:

<ChooseIcon key={this.props.formID} setIcon={this.props.setOptionA} />

So every time your key (it can be anything you like, but unique) is changed component will unmount and mount again, with this you can easily control componentDidMount callback.

like image 72
hawk Avatar answered Dec 05 '22 04:12

hawk


If you are using the ChooseIcon component 3 times inside the same parent component, I would suggest you to do the ajax in componentDidMount of the parent component like this (exaclty how you have in your example, in terms of code)

componentDidMount() {
  var url = `http://local.tshirt.net/get-options`;
  axios.get(url)
      .then(res => {
          this.setState({ icons:res.data.icons });
  });
}

and then pass this data down to the ChooseIcon component

render() {
  return (
  //do your stuff
    <ChooseIcon icons={this.state.icons}/>
  )
}

after this you will only need to set the received props in your ChooseIconcomponent, for that you only need to change one line in it's constructor:

constructor(props) {
    super(props);
    this.state = {
        icons: props.icons,  // Changed here!
        iconList: true,
        confirmIcon: false,
        confirmCaption: false,
        selectedIconOptions: '',
        icon_ID: '',
        option_ID: '',
        selectedIcon: ''
    };
    this.setOptionID = this.setOptionID.bind(this);

    this.setIconVisiblity = this.setIconVisiblity.bind(this);
    this.setIconListVisiblity = this.setIconListVisiblity.bind(this);
}
like image 40
gcampes Avatar answered Dec 05 '22 05:12

gcampes