Search code examples
javascriptreactjsuse-state

How to independently set a button click in react?


I am trying to figure out on how to set a button that can independently be disabled when using the .map function. So I created a state whenever the button is clicked, it disables that specific button. However, it only disables all of the buttons which is not what i wanted. Is there a way to make the buttons have their own click event which can be disabled according to the index?

  const [click, setClick] = useState(false);
  const array = ["item 1", "item 2", "item 3"];

  const disableClick = () => {
    setClick(true);
  };
  
  return (
    <div className="App">
      {array.map((item) => (
        <div>
          <h2>{item}</h2>
          {!click ? (
            <button onClick={disableClick}>CLICK {item}</button>
          ) : (
            <button disabled>Button clicked</button>
          )}
        </div>
      ))}
    </div>
  );

Solution

  • Move the click handler and useState in a separate component.

    const ButtonView = (textContent) => {
      const [disabled, setDisabled] = useState(false);
    
      const onClick = () => {
        setDisabled(true);
      };
    
      if (disabled) {
        return <button disabled={disabled}>Button clicked</button>;
      }
    
      return <button onClick={onClick}>CLICK {textContent}</button>;
    };
    
    export const View = () => {
      const array = ["item 1", "item 2", "item 3"];
      
      return (
        <div className="App">
          {array.map((item, key) => (
            <div key={key}>
              <h2>{item}</h2>
              <ButtonView textContent={item} />
            </div>
          ))}
        </div>
      );
    };
    

    Or do this:

    const ButtonView = (textContent) => {
      const [disabled, setDisabled] = useState(false);
    
      const onClick = () => {
        setDisabled(true);
      };
      const content = disabled ? "Button clicked" : textContent
      return <button disabled={disabled} onClick={onClick}>CLICK {content}</button>;
    };