как создать повторно используемое состояние в хуках реакции? - PullRequest
2 голосов
/ 03 августа 2020

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

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

Кроме того, предположим, что у каждого из них есть свой значок и текст, мы должны иметь возможность при нажатии кнопки изменить текст на COPIED и изменить значок кнопки

Вот как здесь.

enter image description here

Here is what I have so far

    import React, { useState, useEffect, useRef } from 'react';
    
    function Mata() {
    const [isCopied, setIsCopied] = useState(0);
    
    
        return (
             Копировать что-либо  Копировать что-нибудь  Копировать Imgae  Копировать текст  Копировать ссылку  )} экспортировать Mata по умолчанию 

Как я могу создать только одно состояние, например, const[isCopied, setIsCopied] = useState(); и использовать его в любой кнопке, связанной с копированием чего-либо в пользовательском интерфейсе?

Ответы [ 3 ]

4 голосов
/ 03 августа 2020

Возможно, создайте свой собственный компонент React, который инкапсулирует вашу идею, и используйте этот компонент.

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

Ниже простой фрагмент.

import React, { useState } from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <ColouredButton title="Copy something" />
      <ColouredButton title="Copy something" />
      <ColouredButton title="Copy Imgae" />
      <ColouredButton title="Copy text" />
      <ColouredButton title="Copy Link" />
    </div>
  );
}

const ColouredButton = props => {
  const [isCopied, setIsCopied] = useState(0);
  return (
    <button
      style={{ backgroundColor: isCopied ? "#262626" : "#F3F3F3" }}
      className={`btn1 ${isCopied && activeTab}`}
      onClick={() => setIsCopied(prevState => !prevState)}
    >
      {props.title}
    </button>
  );
};
1 голос
/ 03 августа 2020

Вероятно, здесь три отдельных ответа:

Я бы просто использовал файл useState calls

Поскольку вы сказали, что все обработчики разделены, и вы пишете кнопки отдельно , Я бы просто использовал пять useState звонков. Просто, понятно, избегает перекрестных помех между кнопками.

Но вы сказали, что не хотите этого делать, так что для ответа на # 2 ...: -)

Используйте массив обработчиков и объект для флагов

(на самом деле, мне не нравится этот, как следующий; поэтому прочтите его, но потом продолжайте читать.)

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

function Mata() {
    const [isCopied, setIsCopied] = useState({});

    // ...create handlers...

    const buttonHandlers = [handleBtn1, handleBtn2, handleBtn3, handleBtn4, handleBtn5];

    return (
        <div className="container">
            {buttonHandlers.map((handleBtn, index) => {
                const flag = isCopied[index];
                return <button id={index} style={{ backgroundColor: flag ? '#262626' : '#F3F3F3'}} className={`btn${index+1} ${flag && activeTab}`} onClick={handleBtn}>Copy anything</button>;
            })}
        </div>
    );
}

В функции-обработчике:

function handleBtn1(evt) {
    // ...logic...
    if (/*...need to set the flag...*/) {
        setIsCopied(isCopied => ({...isCopied, [evt.target.id]: true}));
    } else if (/*...need to clear the flag...*/) {
        setIsCopied(isCopied => ({...isCopied, [evt.target.id]: true}));
    }
}

Кто-то может вам сказать, что id значения не могут начинаться с цифр. Это неправильно, могут. Это селекторы CSS ID, которые не могут начинаться с неэкранированного di git, но мы здесь не используем CSS.

Используйте объект для флагов, введенных ключом id button

Или полностью отказаться от массива, так как он больше не покупает вас:

function Mata() {
    const [isCopied, setIsCopied] = useState({});

    // ...create handlers...

    return (
        <div className="container">
            <button id="btn1" style={{ backgroundColor: isCopied.btn1 ? '#262626' : '#F3F3F3'}} className={`btn1 ${isCopied.btn1 && activeTab}`} onClick={handleBtn1}>Copy anything</button>
            <button id="btn2" style={{ backgroundColor: isCopied.btn2 ? '#262626' : '#F3F3F3'}} className={`btn2 ${isCopied.btn2 && activeTab}`} onClick={handleBtn2}>Copy something</button>
            <button id="btn3" style={{ backgroundColor: isCopied.btn3 ? '#262626' : '#F3F3F3'}} className={`btn3 ${isCopied.btn3 && activeTab}`} onClick={handleBtn3}>Copy Imgae</button>
            <button id="btn4" style={{ backgroundColor: isCopied.btn4 ? '#262626' : '#F3F3F3'}} className={`btn4 ${isCopied.btn4 && activeTab}`} onClick={handleBtn4}>Copy text</button>
            <button id="btn5" style={{ backgroundColor: isCopied.btn5 ? '#262626' : '#F3F3F3'}} className={`btn5 ${isCopied.btn5 && activeTab}`} onClick={handleBtn5}>Copy Link</button>
        </div>
    );
}
0 голосов
/ 03 августа 2020

Возможно, вы захотите попробовать useReducer() хук для этого.

Если у вас есть опыт использования redux, вы легко поймете эту концепцию.

Подробнее о хуке useReducer здесь.

https://reactjs.org/docs/hooks-reference.html#usereducer

...