如何在反应钩子中创建可重用状态?
Posted
技术标签:
【中文标题】如何在反应钩子中创建可重用状态?【英文标题】:how to create reusable state in react hooks? 【发布时间】:2020-11-23 17:59:05 【问题描述】:我的应用程序中有 5 个按钮,我想根据按钮状态更改背景颜色,所以现在当我单击一个按钮时,它会影响所有按钮,这些按钮用于在 UI 中复制某些内容,每个按钮都复制不同的东西。
注意:我知道我可以为每个按钮创建五个状态,一切都会好起来的,但我认为这是一个糟糕的解决方案。
另外,假设每个都有自己的图标和文本,我们应该可以通过点击按钮将文本更改为COPIED
并更改按钮的图标
喜欢这里。
这是我目前所拥有的
import React, useState, useEffect, useRef from 'react';
function Mata()
const [isCopied, setIsCopied] = useState(0);
return (
<div className="container">
<button style= backgroundColor: isCopied ? '#262626' : '#F3F3F3' className=`btn1 $isCopied && activeTab` onClick=handleBtn1>Copy anything</button>
<button style= backgroundColor: isCopied ? '#262626' : '#F3F3F3' className=`btn2 $isCopied && activeTab` onClick=handleBtn2>Copy something</button>
<button style= backgroundColor: isCopied ? '#262626' : '#F3F3F3' className=`btn3 $isCopied && activeTab` onClick=handleBtn3>Copy Imgae</button>
<button style= backgroundColor: isCopied ? '#262626' : '#F3F3F3' className=`btn4 $isCopied && activeTab` onClick=handleBtn4>Copy text</button>
<button style= backgroundColor: isCopied ? '#262626' : '#F3F3F3' className=`btn5 $isCopied && activeTab` onClick=handleBtn5>Copy Link</button>
</div>
)
export default Mata
我怎样才能只创建一个状态,例如const[isCopied, setIsCopied] = useState()
;并在与在 UI 中复制内容相关的任何按钮中使用它?
【问题讨论】:
【参考方案1】:这里可能有三个不同的答案:
我只会使用文件 useState
调用
由于您说处理程序都是独立的,并且您正在分别编写按钮,所以我只使用五个 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 选择器不能以非转义数字开头,但我们这里没有使用 CSS。
为由按钮的id
键入的标志使用对象
或者完全取消数组,因为它不再给你买太多东西了:
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>
);
【讨论】:
看起来很棒的解决方案,但有一个问题我有五个函数负责每个按钮操作,因为我写道每个按钮都在做其他事情,那么如何在handlebtn
中传递每个函数?通过开关?
@TheDeadMan - 函数是在 Mata
组件中定义的,还是在其他地方定义的?
在 mata 组件中【参考方案2】:
也许创建你自己的 React 组件来封装你的想法,并使用那个组件。
这是一个codesandbox,展示了如何对其进行自定义以满足您的需求,并为每个按钮的 onClick 事件传递一个函数。
下面是一个简单的 sn-p。
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>
);
;
【讨论】:
非常好的解决方案,我的兄弟,Gandzal 假设单击每个按钮,您需要更改文本和图标,如此处ibb.co/m9b0brz,我们如何使用您的解决方案来完成?【参考方案3】:您可能想尝试useReducer()
挂钩。
如果你之前有使用过redux的经验,你可以很容易理解这个概念。
您可以在此处阅读有关 useReducer 挂钩的更多信息。
https://reactjs.org/docs/hooks-reference.html#usereducer
【讨论】:
到目前为止,我一直在寻找可以快速理解的简化解决方案,但谢谢以上是关于如何在反应钩子中创建可重用状态?的主要内容,如果未能解决你的问题,请参考以下文章