【问题标题】:React-hooks handling mutliple buttons state on clickReact-hooks 在点击时处理多个按钮状态
【发布时间】:2023-03-26 19:02:01
【问题描述】:

我的应用程序中有 5 个按钮,我想根据按钮状态更改背景颜色,所以现在当我单击一个按钮时,它会影响所有按钮(切换类),不仅我需要更改按钮颜色,但我还需要隐藏和显示每个按钮的数据,所以我使用条件渲染,默认选项卡是社交媒体。因此,例如,您单击按钮 1 它会更改背景颜色并显示带有信息的 div 等

这是我目前所拥有的

    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

我需要进行哪些更改才能使其正常工作?

【问题讨论】:

    标签: javascript html css reactjs


    【解决方案1】:

    您需要为每个按钮设置单独的状态。我建议使用地图来存储按钮 id 和布尔值是否为“黑色”,即点击处理程序只是切换一个布尔值。我不知道这是否是复制/粘贴代码到 SO 时的拼写错误,但需要在功能组件主体中声明反应状态 in

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

    您还可以使用单击处理程序,方法是将其转换为 curried 回调,并在范围内包含按钮 ID。这使用功能状态更新来浅层复制现有状态并更新封闭按钮 id 的值。

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

    完整代码

    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>
      );
    }
    

    有很多重复的代码,所以一个更 DRY 的版本,其中活动选项卡和按钮作为道具传递。

    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>
      );
    }
    

    这样使用

    const buttons = ["btn1", "btn2", "btn3", "btn4", "btn5"];
    
    ...
    
    <Mata buttons={buttons} />
    

    编辑

    您似乎真的在创建一个“标签管理器”。我建议将状态放样到父级并将Mata 转换为仅呈现“选项卡”按钮的“哑”组件。需要 3 个道具:一个活动选项卡索引、一个按钮数组和一个状态更新回调。

    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>
      );
    }
    

    标签数据示例

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

    示例用法

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

    添加“图标”

    类似于Choosing the Type at Runtime

    如果 SVG 图标还不是 react 组件,请将它们包装成一个简单的功能组件

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

    在标签数据中添加图标字段并将值设置为图标组件

    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 }
    ];
    

    并解构和重命名以渲染

    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>
      );
    }
    

    【讨论】:

    • 谢谢兄弟,我会尝试的,我不仅忘记了另一件事,而且我还想更改另一个状态,例如 const [tab, setTab] = useState('socialmedia'); 用于设置默认按钮,现在我该如何调用例如 @ 987654339@;对于其中一个按钮?
    • @TheDeadMan 我不太确定你想在什么/哪里设置标签值,你能用用例和例子更新你的问题吗?
    • 我已经用更多信息和代码更新了这个问题
    • @TheDeadMan 抱歉耽搁了。我在答案中添加了如何处理选项卡和选择活动选项卡。这是一个简单的示例,但希望对您有所帮助。
    • @TheDeadMan 肯定有。我在答案的末尾添加了一个部分,以将图标组件添加到“选项卡”配置以及如何呈现它。
    【解决方案2】:

    你为什么这样做

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

    而不是这样做?

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

    同样要使用useState,你必须像下面这样编辑你的代码,因为钩子只能在函数组件的主体内部被调用。

    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;
    

    【讨论】:

      猜你喜欢
      • 2020-04-30
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 2019-07-21
      相关资源
      最近更新 更多