skip to Main Content

I have a loop of multiple buttons, I want to change the background color of only the clicked button and not all of them as it happens here :

const [clicked, setClicked] = useState(false);

<div className="flex gap-4 flex-wrap">
    {times.map((time, i) => (
            <div
                key={`time-${i}`}
                className={`${clicked ? 'bg-slate-400' : 'bg-light-gold'}`}
                onClick={() => { setClicked(true) }
             >
                    {time}
            </div>
    ))}
</div>

3

Answers


  1. The UI should be driven by data. You need to create a button list data, each object contains the button’s label, button’s clicked status, etc…

    When the button is clicked, change the value of clicked property of the button.

    import './styles.css';
    import React from 'react';
    
    const initialTimes = [
        { label: 'button 1', clicked: false },
        { label: 'button 2', clicked: false },
        { label: 'button 3', clicked: false },
    ];
    
    export default function App() {
        const [times, setTimes] = React.useState(initialTimes);
        return (
            <div className="App">
                <h1>Hello CodeSandbox</h1>
                <h2>Start editing to see some magic happen!</h2>
    
                <div>
                    {times.map((time, i) => (
                        <button
                            key={`time-${i}`}
                            style={time.clicked ? { background: 'red' } : undefined}
                            onClick={() => {
                                const nextTimes = times.map((t, idx) => (idx === i ? { ...t, clicked: !time.clicked } : t));
                                setTimes(nextTimes);
                            }}>
                            {time.label}
                        </button>
                    ))}
                </div>
            </div>
        );
    }
    

    codesandbox

    Login or Signup to reply.
  2. Should check index of button clicked.

    const [idClicked, setIdClicked] = useState(-1);
    
    <div className="flex gap-4 flex-wrap">
        {times.map((time, i) => (
                <div
                    key={`time-${i}`}
                    className={`${idClicked === i ? 'bg-slate-400' : 'bg-light-gold'}`}
                    onClick={() => { setIdClicked(i) }
                 >
                        {time}
                </div>
        ))}
    </div>
    
    Login or Signup to reply.
  3. Assuming you want to be able to have multiple clicked buttons.

    You could change the useState to be an array in which you place the indexes of the pressed buttons, and remove them if you click again

    const { useState } = React;
    
    const Example = () => {
    
        const [clickedIndexes, setClickedIndexes] = useState([ ]);
    
        return (
            <div>
                <h1>{'Example'}</h1>
                <div className="flex gap-4 flex-wrap">
                    {[...Array(5)].map((time, i) => (
                        <div
                            key={`time-${i}`}
                            className={`${clickedIndexes.includes(i) ? 'clicked' : 'not-clicked'}`}
                            onClick={() => { 
                                var c = [ ...clickedIndexes ];
                                var j = c.indexOf(i);
                                if (j >= 0) {
                                    c.splice(j, 1);
                                } else {
                                    c.push(i);
                                }
                                setClickedIndexes(c);
                            }}
                        >
                        {'Click me!'}
                        </div>
                    ))}
                </div>
            </div>
        )
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    .clicked { color: green; }
    .not-clicked { color: red; }
    <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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search