CraZyDroiD
CraZyDroiD

Reputation: 7105

Render new elements onClick

I have a ReactJS component named as <ImageVoteItem/> . I have a button called 'Add Option'. When I click this button <ImageVoteItem/> should appear. When I click the button again, another <ImageVoteItem/> component should appear.

I have done this using states. But I can only render one <ImageVoteItem/> component. How can I render the same component over and over whenever I click the 'Add Option' button?

My class

class ImageVotePost extends Component {

    constructor() {
        super();

        this.state = {
            addOption: false,
        }
        this.addOption = this.addOption.bind(this);
    }

    addOption() {
        this.setState({
            addOption: true,
        })
    }

    render() {

        return (

            <div className="padding5px margin_bottom10px">
                <ImageVoteItem/>
                <ImageVoteItem/>
                {this.state.addOption ? <ImageVoteItem/> : null}

                <div className="image_add_btn border" onClick={this.addOption}>
                    <div className="width_100 relative_position">
                        <img src={plus} className="plus_icon"/>
                        <a className="add_opt_text">Add Option</a>
                    </div>
                    <input type="file" id="src" className="filetype2"/>
                </div>
            </div>


        )
    }
}

Upvotes: 1

Views: 749

Answers (3)

vipin kumar
vipin kumar

Reputation: 66

try this...

class ImageVotePost extends Component {
        constructor() {
            super();    
            this.state = {
                images: []
            }
        }

        _renderComponent(){
            let images = this.state.images;
            images.push(<ImageVoteItem key={images.length+1}/>);
            this.setState({
            images: images
         });
        }

        render() {
            return (
                <div className="padding5px margin_bottom10px">

                    {this.state.images}

                    <div className="image_add_btn border" onClick={this._renderComponent()}>
                        <div className="width_100 relative_position">
                            <img src={plus} className="plus_icon"/>
                            <a className="add_opt_text">Add Option</a>
                        </div>
                        <input type="file" id="src" className="filetype2"/>
                    </div>

                </div>  
            )
        }
    }

Upvotes: 0

Kamuran S&#246;necek
Kamuran S&#246;necek

Reputation: 3333

I add another option for you as maxImage. If you define any max image value you can add more images component up to it. Before return render you can use a loop to define your image list as array, and you can use it in rendered element.

class ImageVotePost extends Component {

constructor() {
    super();

    this.state = {
        addOption: 0,
        maxImage:10
    }
    this.addOption = this.addOption.bind(this);
}

addOption() {
    this.setState((prevState)=>({
        addOption: ++prevState.addOption,
    })
}


render() {
    let list = []
    for(var i =0 ;i<=this.state.maxImage;i++){
        list.push(<div>{this.state.addOption>i&&
        <ImageVoteItem/>}</div>)
    }
    return (
        <div className="padding5px margin_bottom10px">
            {list}
            <div className="image_add_btn border" onClick={this.addOption}>
                <div className="width_100 relative_position">
                    <img src={plus} className="plus_icon"/>
                    <a className="add_opt_text">Add Option</a>
                </div>
                <input type="file" id="src" className="filetype2"/>
            </div>
        </div>


    )
}

}

If you don't want any limit you can use this also:

class ImageVotePost extends Component {

    constructor() {
        super();

        this.state = {
            imageList: []
        }
        this.addOption = this.addOption.bind(this);
    }

    addOption() {
    let list = this.state.imageList;
    list.push(<ImageVoteItem />);
    this.setState({
        imageList: list
    })
}


    render() {
        return (
            <div className="padding5px margin_bottom10px">
                {list}
                <div className="image_add_btn border" onClick={this.addOption}>
                    <div className="width_100 relative_position">
                        <img src={plus} className="plus_icon"/>
                        <a className="add_opt_text">Add Option</a>
                    </div>
                    <input type="file" id="src" className="filetype2"/>
                </div>
            </div>
        )
    }
}

Upvotes: 1

Mayank Shukla
Mayank Shukla

Reputation: 104369

Instead of using bool, use a numeric value that will store the count of ImageVoteItem (how many time you want to render that component). Then use map on that state value to render the ImageVoteItem Component.

Like this:

class ImageVotePost extends Component {

    constructor() {
        super();    
        this.state = {
            count: 1,
        }
        this.addOption = this.addOption.bind(this);
    }

    addOption() {
        this.setState((prevState) => {
           return {count: prevState.count + 1}
        })
    }

    _renderComponent(){
        let count = this.state.count, uiItems = [];
        while(count--)
           uiItems.push(<ImageVoteItem key={el}/>)
        return UiItems;
    }

    render() {
        return (
            <div className="padding5px margin_bottom10px">

                {this._renderComponent()}

                <div className="image_add_btn border" onClick={this.addOption}>
                    <div className="width_100 relative_position">
                        <img src={plus} className="plus_icon"/>
                        <a className="add_opt_text">Add Option</a>
                    </div>
                    <input type="file" id="src" className="filetype2"/>
                </div>

            </div>  
        )
    }
}

Upvotes: 0

Related Questions