0

I am fairly new to React/Next and I had a quick question.

I am trying to create a button that will increment the number of divs in real time.

Here is my code:

import React from 'react'


const Clown = () => {

    const [clownCounter, setClownCounter] = React.useState(1);

    function addClown(event) {
        event.preventDefault();
    }
    
    return(
        <React.Fragment>
        <div>
            <form>
                 
                {Array.from({ length: clownCounter}, (_unused, index) => index + 1).map(
                    (clownIndex) => {
                        const clownid = `${clownIndex}`
                        return (
                        <div key={clownid } className="clown-box">
                            <label htmlFor={clownid }>Activity {clownIndex}</label>
                            <br />
                            <input type="text" onChange={(e)=> onChangeForm(e)} name={activityId} id={activityId} />
                            <br />
                        </div>
                        )
                    },
                )}
                <span className="clown-add">
                    <button onClick={addClown} onChange={() => { setClownCounter(clownCounter++) }}>Add Clown</button>
                </span>   
                <br />  
            </form>
        </div>
        </React.Fragment>
    )
}
export default Clown

As you can see the goal is to increase the amount of clown-box divs everytime the button is clicked. I think I am close but it is not currently working. Can anyone help?

1
  • Array.from({ length: clownCounter} isn't doing what you'd expect it would do. Commented Apr 4, 2021 at 17:28

2 Answers 2

1

There are few small this wrong with your code.

First, you have an extra comma(,) after the return statement in map function

Second, you are updating state clownCounter on onChange event in button, which is incorrect. You should update it on click and also prevent the default behaviour of form submit on click of button or you can define the button type to be type="button"

Lastly, you need to define your onChangeForm function

const Clown = () => {

    const [clownCounter, setClownCounter] = React.useState(1);
    
    function onChangeForm() {

    }

    function addClown(event) {
        event.preventDefault();
        setClownCounter(prev=> prev+1);
    }
    
    console.log(clownCounter);
    return(
        <div>
            <form>
                 
                {Array.from({ length: clownCounter}, (_unused, index) => index + 1).map(
                    (clownIndex) => {
                        const clownid = `${clownIndex}`;
                        return (
                        <div key={clownid } className="clown-box">
                            <label htmlFor={clownid }>Activity {clownIndex}</label>
                            <br />
                            <input type="text" onChange={(e)=> onChangeForm(e)} name={'activityId'} id={'activityId'} />
                            <br />
                        </div>
                        )
                    })
                }
                <span className="clown-add">
                    <button type="button" onClick={addClown}>Add Clown</button>
                </span>   
                <br />  
            </form>
        </div>
    )
}
ReactDOM.render(<Clown />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app" />

Sign up to request clarification or add additional context in comments.

Comments

0

Edit: Thought issue was caused by Array.from, but, it's not. I've removed that part, but kept the example since OP might find it useful

const { useState } = React;

const Clowns = ({ title }) => {
    const [clownCounter, setClownCounter] = React.useState(1);
    return (
        <div>
            <button onClick={() => setClownCounter(clownCounter + 1)}>
                Add clown
            </button>
            <div className='clowns'>
                {Array.from({ length: clownCounter}, (_unused, index) => index + 1).map((e, i) => (
                    <div>
                        <h4>{`Clown #${i + 1}`}</h4>
                        <img src={`https://placehold.it/150x150&text=Clown%20%23${i + 1}`} />
                    </div>
                ))}
            </div>
        </div>
    );
};

ReactDOM.render(<Clowns />, document.getElementById("react") );
.clowns { display: flex; flex-direction: column; }
h4 { margin-bottom: 5px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>

<div id="react"></div>

2 Comments

Array.from({ length: clownCounter}, (_unused, index) => index + 1) returns an array with elements [1 to clownCounter]
Thanks for pointing that out @ShubhamKhatri, new way for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.