简体   繁体   English

React-hooks 处理多个按钮 state 点击

[英]React-hooks handling mutliple buttons state on click

I have 5 buttons in my app which I would like to change the background color based on button states, so now when I click one button it affects all the buttons (toggle-class), not only that I need to change the button color but also I need to hide and show data for each button, so I am using condition rendering, the default tab is social media.我的应用程序中有 5 个按钮,我想根据按钮状态更改背景颜色,所以现在当我单击一个按钮时,它会影响所有按钮(切换类),不仅我需要更改按钮颜色,而且我还需要隐藏和显示每个按钮的数据,所以我使用条件渲染,默认选项卡是社交媒体。 so, for example, u click button 1 it changes the background color and it shows div withe information, etc因此,例如,您单击按钮 1 它会更改背景颜色并显示带有信息的 div 等

Here is what I have so far这是我到目前为止所拥有的

    import React, { useState, useEffect, useRef } from 'react';
    
    function Mata() {
    const [isBlack, setIsBlack] = useState(0);
    const [tab, setTab] = useState('socialmedia');
    
    const handleBtn1 = (e) =>{
        e.preventDefault();
        setIsBlack(!isBlack);  
        setTab('data1); 
    }
    const handleBtn2 = (e) =>{
        e.preventDefault();
        setIsBlack(!isBlack);  
        setTab('data2'); 
    }
    const handleBtn3 = (e) =>{
        e.preventDefault();
        setIsBlack(!isBlack); 
        setTab('data3'); 
    }
    const handleBtn4 = (e) =>{
        e.preventDefault();
        setIsBlack(!isBlack);  
        setTab('data4'); 
    }
    const handleBtn5 = (e) =>{
        e.preventDefault();
        setIsBlack(!isBlack);  
      setTab('data5'); 
    }
    

        return (
            <div className="container">
                <button style={{ backgroundColor: isBlack ? '#262626' : '#F3F3F3'}} className={`btn1 ${isBlack && activeTab}`} onClick={handleBtn1}>btn1</button>
                <button style={{ backgroundColor: isBlack ? '#262626' : '#F3F3F3'}} className={`btn2 ${isBlack && activeTab}`} onClick={handleBtn2}>btn2</button>
                <button style={{ backgroundColor: isBlack ? '#262626' : '#F3F3F3'}} className={`btn3 ${isBlack && activeTab}`} onClick={handleBtn3}>btn3</button>
                <button style={{ backgroundColor: isBlack ? '#262626' : '#F3F3F3'}} className={`btn4 ${isBlack && activeTab}`} onClick={handleBtn4}>btn4</button>
                <button style={{ backgroundColor: isBlack ? '#262626' : '#F3F3F3'}} className={`btn5 ${isBlack && activeTab}`} onClick={handleBtn5}>btn5</button>
             
    {tab === 'socialmedia' && <>
       ....data
   </div>

{tab === 'data1' && <>
       ....data
   </div>
............
..........
            </div>
        )
    }
    
    export default Mata

What do I need to change to get this working?我需要更改什么才能使其正常工作?

Why are you doing this你为什么做这个

const [isBlack, setIsBlack] = useState(0);

instead of doing this?而不是这样做?

const [isBlack, setIsBlack] = useState(false);

Also to make use of useState you have to edit your code like the following, as hooks can only be called inside of the body of a function component.同样要使用 useState 你必须像下面这样编辑你的代码,因为钩子只能在 function 组件的主体内部调用。

import React, { useState, useEffect, useRef } from "react";

function Mata() {
  const [isBlack, setIsBlack] = useState(false); // correction here

  const handleBtn1 = e => {
    e.preventDefault();
    setIsBlack(!isBlack);
  };
  const handleBtn2 = e => {
    e.preventDefault();
    setIsBlack(!isBlack);
  };
  const handleBtn3 = e => {
    e.preventDefault();
    setIsBlack(!isBlack);
  };
  const handleBtn4 = e => {
    e.preventDefault();
    setIsBlack(!isBlack);
  };
  const handleBtn5 = e => {
    e.preventDefault();
    setIsBlack(!isBlack);
  };
  return (
    <div className="container">
      <button
        style={{ backgroundColor: isBlack ? "#262626" : "#F3F3F3" }}
        className={`btn1 ${isBlack && activeTab}`}
        onClick={handleBtn1}
      >
        btn1
      </button>
      <button
        style={{ backgroundColor: isBlack ? "#262626" : "#F3F3F3" }}
        className={`btn2 ${isBlack && activeTab}`}
        onClick={handleBtn2}
      >
        btn2
      </button>
      <button
        style={{ backgroundColor: isBlack ? "#262626" : "#F3F3F3" }}
        className={`btn3 ${isBlack && activeTab}`}
        onClick={handleBtn3}
      >
        btn3
      </button>
      <button
        style={{ backgroundColor: isBlack ? "#262626" : "#F3F3F3" }}
        className={`btn4 ${isBlack && activeTab}`}
        onClick={handleBtn4}
      >
        btn4
      </button>
      <button
        style={{ backgroundColor: isBlack ? "#262626" : "#F3F3F3" }}
        className={`btn5 ${isBlack && activeTab}`}
        onClick={handleBtn5}
      >
        btn5
      </button>
    </div>
  );
}

export default Mata;

You need individual state for each button.每个按钮都需要单独的 state。 I suggest using a map to store a button id and a boolean value for whether it is "black" or not, ie the click handler simply toggles a boolean value.我建议使用 map 来存储按钮 id 和 boolean 值是否为“黑色”,即点击处理程序只需切换 boolean 值。 I don't know if it was a typo in copy/pasting code to SO, but the react state needs to be declared in in the functional component body.我不知道这是否是复制/粘贴代码到 SO 时的拼写错误,但是需要功能组件主体中声明反应 state。

const [isBlack, setIsBlack] = useState({});

You can also use a single click handler by converting it to a curried callback, taking and enclosing in scope the button id.您还可以使用单击处理程序,方法是将其转换为 curried 回调,获取并包含在 scope 中的按钮 ID。 This uses a functional state update to shallowly copy existing state and updates the value of the enclosed button id.这使用功能 state 更新来浅层复制现有 state 并更新封闭按钮 id 的值。

const handleBtn = btnId => e => {
  e.preventDefault();
  setIsBlack(state => ({
    ...state,
    [btnId]: !state[btnId],
  }));
};

Complete code完整代码

function Mata() {
  const [activeTab, setActiveTab] = useState("activeTab");
  const [isBlack, setIsBlack] = useState({});

  const handleBtn = btnId => e => {
    e.preventDefault();
    setIsBlack(state => ({
      ...state,
      [btnId]: !state[btnId]
    }));
  };

  return (
    <div className="container">
      <button
        style={{ backgroundColor: isBlack["btn1"] ? "#262626" : "#F3F3F3" }}
        className={`btn1 ${isBlack["btn1"] && activeTab}`}
        onClick={handleBtn("btn1")}
      >
        btn1
      </button>
      <button
        style={{ backgroundColor: isBlack["btn2"] ? "#262626" : "#F3F3F3" }}
        className={`btn2 ${isBlack["btn2"] && activeTab}`}
        onClick={handleBtn("btn2")}
      >
        btn2
      </button>
      <button
        style={{ backgroundColor: isBlack["btn3"] ? "#262626" : "#F3F3F3" }}
        className={`btn3 ${isBlack["btn3"] && activeTab}`}
        onClick={handleBtn("btn3")}
      >
        btn3
      </button>
      <button
        style={{ backgroundColor: isBlack["btn4"] ? "#262626" : "#F3F3F3" }}
        className={`btn4 ${isBlack["btn4"] && activeTab}`}
        onClick={handleBtn("btn4")}
      >
        btn4
      </button>
      <button
        style={{ backgroundColor: isBlack["btn5"] ? "#262626" : "#F3F3F3" }}
        className={`btn5 ${isBlack["btn5"] && activeTab}`}
        onClick={handleBtn("btn5")}
      >
        btn5
      </button>
    </div>
  );
}

There is a lot of repeated code, so a more DRY version where active tab and buttons are passed as props.有很多重复的代码,所以一个更干的版本,其中活动选项卡和按钮作为道具传递。

function Mata({ activeTab = '', buttons }) {
  const [isBlack, setIsBlack] = useState({});

  const handleBtn = btnId => e => {
    e.preventDefault();
    setIsBlack(state => ({
      ...state,
      [btnId]: !state[btnId]
    }));
  };

  return (
    <div className="container">
      {buttons.map(btn => (
        <button
          style={{ backgroundColor: isBlack[btn] ? "#262626" : "#F3F3F3" }}
          className={`btn1 ${isBlack[btn] && activeTab}`}
          onClick={handleBtn(btn)}
        >
          {btn}
        </button>
      ))}
    </div>
  );
}

Used as such这样使用

const buttons = ["btn1", "btn2", "btn3", "btn4", "btn5"];

...

<Mata buttons={buttons} />

编辑处理多个按钮状态 onClick 的反应钩子

Edit编辑

Seems you are really creating a "tab manager".似乎你真的在创建一个“标签管理器”。 I suggest lofting state to the parent and converting Mata to a "dumb" component that simply renders the "tab" buttons.我建议将 state 放样到父级,并将Mata转换为仅呈现“选项卡”按钮的“哑”组件。 Takes 3 props: an active tab index, array of buttons, and a state update callback.需要 3 个道具:活动标签索引、按钮数组和 state 更新回调。

function Mata({ activeTab = -1, buttons, setActiveTab }) {
  return (
    <div className="container">
      {buttons.map((btn, i) => {
        const isActive = i === activeTab;
        return (
          <button
            key={btn.id}
            style={{ backgroundColor: isActive ? "#262626" : "#F3F3F3" }}
            className={`${btn.id} ${isActive && activeTab}`}
            onClick={() => setActiveTab(i)}
          >
            {btn.id}
          </button>
        );
      })}
    </div>
  );
}

Example tabs data示例选项卡数据

const tabs = [
  { id: "btn1", data: "data1" },
  { id: "btn2", data: "data2" },
  { id: "btn3", data: "data3" },
  { id: "btn4", data: "data4" },
  { id: "btn5", data: "data5" }
];

Example usage示例用法

<Mata activeTab={activeTab} buttons={tabs} setActiveTab={setActiveTab} />

{activeTab === -1 ? (
  <div>Social Media</div>
) : (
  <div>{tabs[activeTab].data}</div>
)}

编辑处理多个按钮状态 onClick(选项卡)的反应钩子

Adding "Icons"添加“图标”

Similar to Choosing the Type at Runtime类似于在运行时选择类型

If SVG icons are not already react components, wrap them into a simple functional component如果 SVG 图标还不是 react 组件,将它们包装成一个简单的功能组件

const Icon1 = () => <svg>...</svg>;

Add an icon field to the tabs data and set the value to the icon component将图标字段添加到选项卡数据并将值设置为图标组件

const tabs = [
  { id: "btn1", data: "data1", icon: Icon1 },
  { id: "btn2", data: "data2", icon: Icon2 },
  { id: "btn3", data: "data3", icon: Icon3 },
  { id: "btn4", data: "data4", icon: Icon4 },
  { id: "btn5", data: "data5", icon: Icon5 }
];

And destructure and rename to render并解构和重命名渲染

function Mata({ activeTab = -1, buttons, setActiveTab }) {
  return (
    <div className="container">
      {buttons.map((btn, i) => {
        const isActive = i === activeTab;
        const { icon: Icon, id } = btn; // <-- rename icon -> Icon

        return (
          <button
            key={id}
            style={{ backgroundColor: isActive ? "#262626" : "#F3F3F3" }}
            className={`${id} ${isActive && activeTab}`}
            onClick={() => setActiveTab(i)}
          >
            <Icon /> {id} // <-- render icon component
          </button>
        );
      })}
    </div>
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 计数增量器未在反应挂钩中设置状态 - Count Incrementer not setting state in react-hooks 在更新 state 和 react-hooks 时执行异步代码 - Executing async code on update of state with react-hooks React-Hooks:使用 arrays 时的州的特殊行为 - React-Hooks: State's Peculiar Behavior when working with arrays React挂钩:如何使用react-hooks / exhaustive-deps规则在没有无限循环的情况下读取和更新挂钩中的状态 - React hooks: How to read & update state in hooks without infinite loops with react-hooks/exhaustive-deps rule React / React-Hooks:我需要根据有效/无效状态在输入字段上运行验证 - React/React-Hooks: I need to run a validation on an input field depending on active/inactive state State(useState)在页面刷新时不持久 react-hooks react-bootstrap - State (useState) not persisting on page refresh react-hooks react-bootstrap 仅更新我更改其他人的日期 state 不应更新或更改 ReactJS/React-Hooks - Only update the date I change others state should not update or change ReactJS/React-Hooks 使用钩子处理 React 中的文件上传状态 - Handling File Upload state in React with hooks React Hooks 错误处理将状态转换为函数 - React Hooks Error Handling Turns State To Function React-Hooks:在 ContextAPI 中未定义“警报” - React-Hooks: 'Alert' is undefined in ContextAPI
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM