Реагирующие хуки, обрабатывающие состояние нескольких кнопок при нажатии - PullRequest
0 голосов
/ 02 августа 2020

В моем приложении 5 кнопок, для которых я хотел бы изменить цвет фона в зависимости от состояния кнопок, поэтому теперь, когда я нажимаю одну кнопку, она влияет на все кнопки (класс переключения), а не только на то, что мне нужно изменить цвет кнопки, но также мне нужно скрыть и показать данные для каждой кнопки, поэтому я использую рендеринг условий, вкладка по умолчанию - социальные сети. так, например, при нажатии кнопки 1 цвет фона изменяется и отображается div с информацией, et c

Вот что у меня есть на данный момент

    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

Что мне делать нужно изменить, чтобы это заработало?

Ответы [ 2 ]

1 голос
/ 02 августа 2020

Для каждой кнопки нужно индивидуальное состояние. Я предлагаю использовать карту для хранения идентификатора кнопки и логического значения того, является она «черным» или нет, то есть обработчик кликов просто переключает логическое значение. Я не знаю, была ли это опечатка при копировании / вставке кода в SO, но состояние реакции необходимо объявить в в теле функционального компонента.

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

Вы также можете использовать обработчик одиночного щелчка, преобразовав его в каррированный обратный вызов, взяв и заключив в область видимости идентификатор кнопки. При этом используется обновление функционального состояния для поверхностного копирования существующего состояния и обновления значения идентификатора заключенной кнопки.

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} />

Edit react hooks handling multiple buttons state 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. Takes 3 props: an active tab index, array of buttons, and a state update callback.

function Mata({ activeTab = -1, buttons, setActiveTab }) {
  return (
     {buttons.map ((btn , i) => {const isActive = i === activeTab; return ( setActiveTab (i)}> {btn.id} );})} ); } 

Пример данных вкладок

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

Edit react hooks handling multiple buttons state onClick (tabs)

Adding "Icons"

Similar to Выбор типа во время выполнения

Если значки SVG еще не являются реагирующими компонентами, оберните их в простой функциональный компонент

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>
  );
}
1 голос
/ 02 августа 2020

Почему вы делаете это

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...