反应力componentDidMount

时间:2017-01-12 16:23:47

标签: reactjs

我有以下内容:

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;

&#34; ChooseIcon&#34;是一个将被使用3次的组件因此每次我到达它时我需要将其状态恢复,就好像这是第一次。

理想情况下,我每次都需要进行此ajax调用:

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

有没有办法从父组件手动调用componentDidMount?

3 个答案:

答案 0 :(得分:14)

React通过key属性处理组件生命周期。例如:

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

因此,每当您的key(它可以是您喜欢的任何内容,但都是唯一的)更改后,组件将卸载并再次装入,您可以轻松控制componentDidMount回调。

答案 1 :(得分:2)

父组件可以使用ref直接调用该函数。

然而,试图强制这个功能感觉就像一个气味。也许将组件树中的状态提升到更高的位置可以解决这个问题。这样,父组件将告诉ChooseIcon要显示的内容,并且不需要再次调用componentDidMount。另外,我假设Ajax调用也可以发生一次。

答案 2 :(得分:2)

如果您在同一个父组件中使用componentDidMount组件3次,我建议您像这样在父组件的componentDidMount() { var url = `http://local.tshirt.net/get-options`; axios.get(url) .then(res => { this.setState({ icons:res.data.icons }); }); } 中执行ajax(exaclty在示例中的方式) ,就代码而言)

ChooseIcon

然后将此数据传递给render() { return ( //do your stuff <ChooseIcon icons={this.state.icons}/> ) } 组件

ChooseIcon

在此之后,您只需要在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); } 组件中设置收到的道具,因为您只需更改其中的一行构造函数:

=IF(C9="Post 2000",1, IF(C9="1991-2000",1.19,IF(C9="1951-1990",1.29,IF(C9="Pre 1951",1.59))))