admin管理员组

文章数量:1023263

I have some buttons and I'm trying to add active class for clicked button. But when I click one of the buttons, all buttons are getting active class.

const { useState } = React;
const { render } = ReactDOM;
const node = document.getElementById("root");

const Button = ({ message }) => {
  const [condition, setCondition] = useState(false);
  return (
    <div>
    {
    Object.keys(res).map((data) => (
    <Button className={condition ? "button toggled" : "button"} onClick=. 
     {() => {
      setCondition(!condition)}
     }}
     ))
      }
    </div>
  );
   //Updated
   Object.keys(res).map((data) => (
    <Button className={condition ? "button toggled" : "button"} onClick=. 
     {() => {
      setCondition(condition === "off" ? "on" : "off")}
     }}
     ))
      }
    </div>
  ); //This can be modified to work for button clicked. Because active class is added to all buttons, if one of them is clicked
};
render(<Button message="Click me if you dare!" />, node);

This is working if I click the first button, but if I click again the same button, this active class should be removed

I have some buttons and I'm trying to add active class for clicked button. But when I click one of the buttons, all buttons are getting active class.

const { useState } = React;
const { render } = ReactDOM;
const node = document.getElementById("root");

const Button = ({ message }) => {
  const [condition, setCondition] = useState(false);
  return (
    <div>
    {
    Object.keys(res).map((data) => (
    <Button className={condition ? "button toggled" : "button"} onClick=. 
     {() => {
      setCondition(!condition)}
     }}
     ))
      }
    </div>
  );
   //Updated
   Object.keys(res).map((data) => (
    <Button className={condition ? "button toggled" : "button"} onClick=. 
     {() => {
      setCondition(condition === "off" ? "on" : "off")}
     }}
     ))
      }
    </div>
  ); //This can be modified to work for button clicked. Because active class is added to all buttons, if one of them is clicked
};
render(<Button message="Click me if you dare!" />, node);

This is working if I click the first button, but if I click again the same button, this active class should be removed

Share Improve this question edited Feb 19, 2020 at 10:00 Rexhep Rexhepi asked Feb 18, 2020 at 15:24 Rexhep RexhepiRexhep Rexhepi 1373 silver badges15 bronze badges 5
  • Just use another state variable for each additional button – Chris Commented Feb 18, 2020 at 15:25
  • I have edited my question sorry, buttons are counted from Object.keys(data) – Rexhep Rexhepi Commented Feb 18, 2020 at 15:31
  • I take it the number of keys in your object can be dynamic? – Chris Commented Feb 18, 2020 at 15:32
  • @Chris yes. they can be dynamic – Rexhep Rexhepi Commented Feb 18, 2020 at 15:33
  • Then you might want to change your state variable from being a boolean to being an object with key-value pairs that would correspond to that of your object – Chris Commented Feb 18, 2020 at 15:35
Add a ment  | 

5 Answers 5

Reset to default 2

Here is a very naive solution, but it will help you understand the problem.

If you're on a real project, I suggest you to use an existing library (that can be found by searching react toggle button group)

import React, {useState} from "react";

const defaultButtons = [
    {id: 1},
    {id: 2},
    {id: 3},
    {id: 4}
];

export default function App() {
    const [toggledButtonId, setToggledButtonId] = useState(null);

    function toggleButton(button) {
        setToggledButtonId(button.id);
    }

    return (
        <div>
            {defaultButtons.map(button => {
                const isToggled = button.id === toggledButtonId;
                return (
                    <button
                        key={button.id}
                        className={isToggled ? "toggledButtonId toggled" : "toggledButtonId"}
                        onClick={() => toggleButton(button)}>
                        {String(isToggled)}
                    </button>
                )
            })}
        </div>
    )
}

You need to use a seperate state handler for each button:

const Button = ({ message }) => {
 const [condition, setCondition] = useState(false);
 const [condition2, setCondition2] = useState(false);
  return (
    <div>
    <div
      onClick={() => setCondition(!condition)}
      className={condition ? "button toggled" : "button"}
    >
      {message}
    </div>  
      <div
      onClick={() => setCondition(!condition2)}
      className={condition2 ? "button toggled" : "button"}
    >
      {message}
    </div>  
    </div>
  );
};

render(<Button message="Click me if you dare!" />, node);

maybe you want to check this.

https://codesandbox.io/embed/import-css-file-react-vs488?fontsize=14&hidenavigation=1&theme=dark

You could create ponent Button with state within and use this ponent to populate buttons. Probably you can use :active CSS selector and avoid js at all

import React, {useState, useCallback} from "react";

const defaultButtons = [
    {id: 1},
    {id: 2},
    {id: 3},
    {id: 4}
];

export default function App() {
    const [toggledButtonId, setToggledButtonId] = useState(false);

    function toggleButton(button) {
        setToggledButtonId(button.id);
    }
      const toggleButton = useCallback((id) => setToggledButtonId(state => id), [toggledButtonId]);

    return (
        <div>
            {defaultButtons.map(button => {
                const isToggled = button.id === toggledButtonId;
                return (
                    <button
                        key={button.id}
                        className={isToggled ? "toggledButtonId toggled" : "toggledButtonId"}
                        onClick={toggleButton(button.id)}>
                        {String(isToggled)}
                    </button>
                )
            })}
        </div>
    )
}

I have some buttons and I'm trying to add active class for clicked button. But when I click one of the buttons, all buttons are getting active class.

const { useState } = React;
const { render } = ReactDOM;
const node = document.getElementById("root");

const Button = ({ message }) => {
  const [condition, setCondition] = useState(false);
  return (
    <div>
    {
    Object.keys(res).map((data) => (
    <Button className={condition ? "button toggled" : "button"} onClick=. 
     {() => {
      setCondition(!condition)}
     }}
     ))
      }
    </div>
  );
   //Updated
   Object.keys(res).map((data) => (
    <Button className={condition ? "button toggled" : "button"} onClick=. 
     {() => {
      setCondition(condition === "off" ? "on" : "off")}
     }}
     ))
      }
    </div>
  ); //This can be modified to work for button clicked. Because active class is added to all buttons, if one of them is clicked
};
render(<Button message="Click me if you dare!" />, node);

This is working if I click the first button, but if I click again the same button, this active class should be removed

I have some buttons and I'm trying to add active class for clicked button. But when I click one of the buttons, all buttons are getting active class.

const { useState } = React;
const { render } = ReactDOM;
const node = document.getElementById("root");

const Button = ({ message }) => {
  const [condition, setCondition] = useState(false);
  return (
    <div>
    {
    Object.keys(res).map((data) => (
    <Button className={condition ? "button toggled" : "button"} onClick=. 
     {() => {
      setCondition(!condition)}
     }}
     ))
      }
    </div>
  );
   //Updated
   Object.keys(res).map((data) => (
    <Button className={condition ? "button toggled" : "button"} onClick=. 
     {() => {
      setCondition(condition === "off" ? "on" : "off")}
     }}
     ))
      }
    </div>
  ); //This can be modified to work for button clicked. Because active class is added to all buttons, if one of them is clicked
};
render(<Button message="Click me if you dare!" />, node);

This is working if I click the first button, but if I click again the same button, this active class should be removed

Share Improve this question edited Feb 19, 2020 at 10:00 Rexhep Rexhepi asked Feb 18, 2020 at 15:24 Rexhep RexhepiRexhep Rexhepi 1373 silver badges15 bronze badges 5
  • Just use another state variable for each additional button – Chris Commented Feb 18, 2020 at 15:25
  • I have edited my question sorry, buttons are counted from Object.keys(data) – Rexhep Rexhepi Commented Feb 18, 2020 at 15:31
  • I take it the number of keys in your object can be dynamic? – Chris Commented Feb 18, 2020 at 15:32
  • @Chris yes. they can be dynamic – Rexhep Rexhepi Commented Feb 18, 2020 at 15:33
  • Then you might want to change your state variable from being a boolean to being an object with key-value pairs that would correspond to that of your object – Chris Commented Feb 18, 2020 at 15:35
Add a ment  | 

5 Answers 5

Reset to default 2

Here is a very naive solution, but it will help you understand the problem.

If you're on a real project, I suggest you to use an existing library (that can be found by searching react toggle button group)

import React, {useState} from "react";

const defaultButtons = [
    {id: 1},
    {id: 2},
    {id: 3},
    {id: 4}
];

export default function App() {
    const [toggledButtonId, setToggledButtonId] = useState(null);

    function toggleButton(button) {
        setToggledButtonId(button.id);
    }

    return (
        <div>
            {defaultButtons.map(button => {
                const isToggled = button.id === toggledButtonId;
                return (
                    <button
                        key={button.id}
                        className={isToggled ? "toggledButtonId toggled" : "toggledButtonId"}
                        onClick={() => toggleButton(button)}>
                        {String(isToggled)}
                    </button>
                )
            })}
        </div>
    )
}

You need to use a seperate state handler for each button:

const Button = ({ message }) => {
 const [condition, setCondition] = useState(false);
 const [condition2, setCondition2] = useState(false);
  return (
    <div>
    <div
      onClick={() => setCondition(!condition)}
      className={condition ? "button toggled" : "button"}
    >
      {message}
    </div>  
      <div
      onClick={() => setCondition(!condition2)}
      className={condition2 ? "button toggled" : "button"}
    >
      {message}
    </div>  
    </div>
  );
};

render(<Button message="Click me if you dare!" />, node);

maybe you want to check this.

https://codesandbox.io/embed/import-css-file-react-vs488?fontsize=14&hidenavigation=1&theme=dark

You could create ponent Button with state within and use this ponent to populate buttons. Probably you can use :active CSS selector and avoid js at all

import React, {useState, useCallback} from "react";

const defaultButtons = [
    {id: 1},
    {id: 2},
    {id: 3},
    {id: 4}
];

export default function App() {
    const [toggledButtonId, setToggledButtonId] = useState(false);

    function toggleButton(button) {
        setToggledButtonId(button.id);
    }
      const toggleButton = useCallback((id) => setToggledButtonId(state => id), [toggledButtonId]);

    return (
        <div>
            {defaultButtons.map(button => {
                const isToggled = button.id === toggledButtonId;
                return (
                    <button
                        key={button.id}
                        className={isToggled ? "toggledButtonId toggled" : "toggledButtonId"}
                        onClick={toggleButton(button.id)}>
                        {String(isToggled)}
                    </button>
                )
            })}
        </div>
    )
}

本文标签: javascriptReacttoggle class useState hook form several buttonStack Overflow