Reputation: 65
I have 20 buttons and I wanted to apply class .active on the button which is clicked and the rest will inactive. Suppose I clicked on button one then I want to add an active class to button one and then when I clicked on button two then button two will get an active class and active class removed from button one.
import React from "react";
const PaginationButtonsList = (props) => {
const handleClick = (event) =>{
}
return (
<div className="pagination-buttons-list">
<button onClick={handleClick} id="button-1">1</button>
<button onClick={handleClick} id="button-2">2</button>
<button onClick={handleClick} id="button-3">3</button>
<button onClick={handleClick} id="button-4">4</button>
<button onClick={handleClick} id="button-5">5</button>
<button onClick={handleClick} id="button-6">6</button>
<button onClick={handleClick} id="button-7">7</button>
<button onClick={handleClick} id="button-8">8</button>
<button onClick={handleClick} id="button-9">9</button>
<button onClick={handleClick} id="button-10">10</button>
<button onClick={handleClick} id="button-11">11</button>
<button onClick={handleClick} id="button-12">12</button>
<button onClick={handleClick} id="button-13">13</button>
<button onClick={handleClick} id="button-14">14</button>
<button onClick={handleClick} id="button-15">15</button>
<button onClick={handleClick} id="button-16">16</button>
<button onClick={handleClick} id="button-17">17</button>
<button onClick={handleClick} id="button-18">18</button>
<button onClick={handleClick} id="button-19">19</button>
<button onClick={handleClick} id="button-20">20</button>
</div>
);
};
export { PaginationButtonsList };
Upvotes: 0
Views: 1385
Reputation: 510
I assume that you don't want a button with just generic numbers for text. So you will need to:
.
import React, {useState} from "react";
/* Change this number to any text and add as many as you need */
let buttonText = ['1','2','3','4','5']
const PaginationButtonsList = (props) => {
const [activeIndex, setActiveIndex] = useState(-1)
const handleClick = (value) =>{
setActiveIndex(value)
}
return (
<div className="pagination-buttons-list">
{buttonText.map((text,index)=> (
<button onClick={()=>handleClick(index)} class={index === activeIndex ? "active" :""} id={`button-${index}`}>{text}</button>
)
</div>
);
};
export { PaginationButtonsList };
Upvotes: 3
Reputation: 135237
You only need to save a single integer of state, the index corresponding to the active button -
function App({ buttons = [] }) {
const [active, setActive] = React.useState(-1)
const toggle = index => event => setActive(index)
return <div>
{buttons.map((b, key) =>
<button
className={active == key && 'active'}
onClick={toggle(key)}
children={b}
/>
)}
</div>
}
ReactDOM.render(
<App buttons={["🍟","🥨","🍐","🌮","🥤"]} />,
document.body
)
button { margin-right: 0.5em; font-size: 1.2em; border-radius: 5px; padding: 0 0.4em; }
button:hover { cursor: pointer; background-color: #cdcdcd; }
button.active { background-color: lightgreen; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
If you want repeated clicks to the same button to toggle the active off, if the same button is clicked twice, you can restore the initial active
state of -1
-
function App({ buttons = [] }) {
const [active, setActive] = React.useState(-1)
const toggle = index => event =>
setActive(index == active ? -1 : index) // <-
return <div>
{buttons.map((b, key) =>
<button
className={active == key && 'active'}
onClick={toggle(key)}
children={b}
/>
)}
</div>
}
ReactDOM.render(
<App buttons={["🍟","🥨","🍐","🌮","🥤"]} />,
document.body
)
button { margin-right: 0.5em; font-size: 1.2em; border-radius: 5px; padding: 0 0.4em; }
button:hover { cursor: pointer; background-color: #cdcdcd; }
button.active { background-color: lightgreen; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
Upvotes: 0
Reputation: 63524
One way of approaching this would be to create an array of button objects that you can use to configure your component. Each button object in the array would have the shape { id: number, text: string, active: boolean }
that defines it. You can that add that configuration to state.
When a button is clicked you reset the active values of each button (by updating a deep-copy the current state), update the active value of the clicked button, and finally create a new state with the updated data. That new state will be reflected in the component when it's re-rendered.
This method also has the advantages that 1) you encapsulate the button config in one place without the need for separate states, and 2) you don't need to hard-code all the buttons in the JSX - you can map
over the button configuration to create an array of buttons using a useful Button component.
const { useState } = React;
// Pass in the button config
function Example({ btnConfig }) {
// Set state with the config
const [ btns, setBtns ] = useState(btnConfig);
// When a button is clicked grab its id from its dataset,
// make a deep copy of the state resetting all of the active
// values for each button to false, find the index of the button
// that was clicked, and then set its active value to true.
// Finally update the state to re-render the component
function handleClick(e) {
const { id } = e.target.dataset;
const reset = btns.map(btn => ({ ...btn, active: false }));
const index = reset.findIndex(btn => btn.id === +id);
reset[index].active = true;
setBtns(reset);
}
// `map` over the state and create JSX using a
// Button component passing down the properties from
// the objects in state as well as a reference to the
// `handleClick` function
return (
<div>
{btns.map(btn => {
const { id, text, active } = btn;
return (
<Button
key={id}
id={id}
active={active}
text={text}
handleClick={handleClick}
/>
);
})}
</div>
);
}
// Accepts the button props and returns a button. If
// the active value is true then apply the "active" class
function Button({ id, text, active, handleClick }) {
return (
<button
data-id={id}
onClick={handleClick}
className={active && 'active'}
>{text}
</button>
);
}
// Create a button config - an array of button of objects
const btnConfig = Array.from({length: 10}, (_, i) => {
const id = i + 1;
return { id, text: id, active: false };
});
// Pass in the button config to the component
ReactDOM.render(
<Example btnConfig={btnConfig} />,
document.getElementById('react')
);
button { margin-right: 0.5em; font-size: 1.2em; border-radius: 5px; padding: 0 0.4em; }
button:hover { cursor: pointer; background-color: #cdcdcd; }
button.active { background-color: lightgreen; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Upvotes: 0
Reputation: 33749
You can create an array state holding information for each button.
In each button state object in the array, include a property for whether the button is active or not. Then use this property when mapping the button states to actual buttons and set the active class if the button's state is active.
When a button is clicked, update the state array: make that button's state active and make every other button's state inactive.
Here's a complete example with types:
import {default as React, type ReactElement, useState} from 'react';
type ButtonState = {
active: boolean;
id: number;
};
const PaginationButtonsList = () => {
const [buttonStates, setButtonStates] = useState<ButtonState[]>(Array.from(
{length: 20},
(_, i) => ({id: i + 1, active: false}),
));
const createButtonFromState = (
{active, id}: ButtonState,
index: number,
): ReactElement => {
const setActiveExclusive = () => {
setButtonStates(arr => arr.map((state, i) => ({
...state,
active: i === index,
})));
};
const buttonProps = {
className: active ? 'active' : '',
id: `button-${id}`,
key: id,
onClick: setActiveExclusive,
};
return (<button {...buttonProps}>{id}</button>);
};
return (
<div className="pagination-buttons-list">
{buttonStates.map(createButtonFromState)}
</div>
);
};
Code in the TypeScript Playground
Upvotes: -1