如何使布尔状态 setter 可重用
How to make boolean state setter reusable
我目前有一个包含 headers 的页面:h1、h2、h3。我希望他们的文本可以被用户点击编辑,所以基本上 header 将变成输入类型='text' 然后当用户完成输入他的值时恢复到 header输入。我使用 useReducer 挂钩使此功能运行良好,我在其中分派与每个相关的相应值。但是,我正在努力弄清楚如何使 textIsEditing prop/boolean 可在所有 3 个组件中重复使用。让我用代码来解释一下:
JSON数据:
{
"name":"Click to rename One",
"campaigntype": "Click to rename Two",
"description": "Click to rename Three",
}
包含 3 个 header 的组件:
export default function MetaData() {
const [nameIsEditing, setNameEditing] = useState(false);
const [campaignIsEditing, setCampaignIsEditing] = useState(false);
const [descriptionIsEditing, setDescriptionIsEditing] = useState(false);
function toggleNameEdit(){
setNameEditing(!nameIsEditing);
}
function toggleCampaignEdit(){
setCampaignIsEditing(!campaignIsEditing);
}
function toggleDescriptionEdit(){
setDescriptionIsEditing(!descriptionIsEditing);
}
const initialState = jsonData;
const [metaData, dispatch] = useReducer(metaDataReducer, initialState);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const defaultMetaValue = metaData[e.target.name as keyof MetaState];
dispatch({ type: e.target.name, value: e.target.value === '' ? defaultMetaValue : e.target.value });
};
return (
<Grid className='menuItem' container direction='column'>
{nameIsEditing ?
<RenameInput name='name' textStyle='h3' onClickAway={toggleNameEdit} onSubmit={toggleNameEdit} adName={metaData.name} onChange={handleChange} />
:
<H1 onClick={toggleNameEdit}>{metaData.name}</H1>}
{campaignIsEditing ?
<RenameInput name='campaigntype' textStyle='subtitle2' onClickAway={toggleCampaignEdit} onSubmit={toggleCampaignEdit} campaignType={metaData.campaigntype} onChange={handleChange} />
:
<H2 onClick={toggleCampaignEdit}>{metaData.campaigntype}</H2>}
{descriptionIsEditing ?
<RenameInput paragraph textStyle='body2' name='description' onClickAway={toggleDescriptionEdit} onSubmit={toggleDescriptionEdit} adDescription={metaData.description} onChange={handleChange} />
:
<H3 onClick={toggleDescriptionEdit} className='meta-description'>{metaData.description}</H3>}
</Grid>);
}
减速器:
const metaDataReducer = (state: MetaState, action: ActionType) => {
if (action.type in state) {
return { ...state, [action.type]: action.value };
} else {
return state;
}
};
重命名输入:
const RenameInput = (props) => {
return (
<ClickAwayListener onClickAway={props.onClickAway}>
<form onSubmit={props.onSubmit}>
<TextInput
defaultValue={props.adName || props.adDescription || props.campaignType}
autoFocus
onChange={props.onChange}
multiline={props.paragraph}
textStyle={props.textStyle}
name={props.name}
/>
</form>
</ClickAwayListener>
);
};
在我的元数据组件上,我真的不喜欢这部分代码
const [nameIsEditing, setNameEditing] = useState(false);
const [campaignIsEditing, setCampaignIsEditing] = useState(false);
const [descriptionIsEditing, setDescriptionIsEditing] = useState(false);
function toggleNameEdit(){
setNameEditing(!nameIsEditing);
}
function toggleCampaignEdit(){
setCampaignIsEditing(!campaignIsEditing);
}
function toggleDescriptionEdit(){
setDescriptionIsEditing(!descriptionIsEditing);
}
我想 re-usable 跨越所有 3 个组件,因为它实际上在做同样的事情。我需要一个函数来处理所有这 3 个,但我真的不确定在哪里或如何执行此操作?我是在减速器中做这个,还是我怎么能把它变成工厂功能?肯定有比我用 {nameIsEditing ? renameComponent : h1
{campaignIsEditing ? renameComponent : h2
{descriptionIsEditing ? renameComponent : h3
做的更好的方法
您应该简单地创建一个新组件 EditableTitle
。它将处理 isEditing
状态,并执行呈现 read-only 标题或 RenameInput
组件的逻辑。
为了处理标题之间的细微差异,您可以将道具发送到EditableTitle
。例如,您可以发送 component
值来呈现 h1
、h2
或您想要的任何其他组件。
我目前有一个包含 headers 的页面:h1、h2、h3。我希望他们的文本可以被用户点击编辑,所以基本上 header 将变成输入类型='text' 然后当用户完成输入他的值时恢复到 header输入。我使用 useReducer 挂钩使此功能运行良好,我在其中分派与每个相关的相应值。但是,我正在努力弄清楚如何使 textIsEditing prop/boolean 可在所有 3 个组件中重复使用。让我用代码来解释一下:
JSON数据:
{
"name":"Click to rename One",
"campaigntype": "Click to rename Two",
"description": "Click to rename Three",
}
包含 3 个 header 的组件:
export default function MetaData() {
const [nameIsEditing, setNameEditing] = useState(false);
const [campaignIsEditing, setCampaignIsEditing] = useState(false);
const [descriptionIsEditing, setDescriptionIsEditing] = useState(false);
function toggleNameEdit(){
setNameEditing(!nameIsEditing);
}
function toggleCampaignEdit(){
setCampaignIsEditing(!campaignIsEditing);
}
function toggleDescriptionEdit(){
setDescriptionIsEditing(!descriptionIsEditing);
}
const initialState = jsonData;
const [metaData, dispatch] = useReducer(metaDataReducer, initialState);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const defaultMetaValue = metaData[e.target.name as keyof MetaState];
dispatch({ type: e.target.name, value: e.target.value === '' ? defaultMetaValue : e.target.value });
};
return (
<Grid className='menuItem' container direction='column'>
{nameIsEditing ?
<RenameInput name='name' textStyle='h3' onClickAway={toggleNameEdit} onSubmit={toggleNameEdit} adName={metaData.name} onChange={handleChange} />
:
<H1 onClick={toggleNameEdit}>{metaData.name}</H1>}
{campaignIsEditing ?
<RenameInput name='campaigntype' textStyle='subtitle2' onClickAway={toggleCampaignEdit} onSubmit={toggleCampaignEdit} campaignType={metaData.campaigntype} onChange={handleChange} />
:
<H2 onClick={toggleCampaignEdit}>{metaData.campaigntype}</H2>}
{descriptionIsEditing ?
<RenameInput paragraph textStyle='body2' name='description' onClickAway={toggleDescriptionEdit} onSubmit={toggleDescriptionEdit} adDescription={metaData.description} onChange={handleChange} />
:
<H3 onClick={toggleDescriptionEdit} className='meta-description'>{metaData.description}</H3>}
</Grid>);
}
减速器:
const metaDataReducer = (state: MetaState, action: ActionType) => {
if (action.type in state) {
return { ...state, [action.type]: action.value };
} else {
return state;
}
};
重命名输入:
const RenameInput = (props) => {
return (
<ClickAwayListener onClickAway={props.onClickAway}>
<form onSubmit={props.onSubmit}>
<TextInput
defaultValue={props.adName || props.adDescription || props.campaignType}
autoFocus
onChange={props.onChange}
multiline={props.paragraph}
textStyle={props.textStyle}
name={props.name}
/>
</form>
</ClickAwayListener>
);
};
在我的元数据组件上,我真的不喜欢这部分代码
const [nameIsEditing, setNameEditing] = useState(false);
const [campaignIsEditing, setCampaignIsEditing] = useState(false);
const [descriptionIsEditing, setDescriptionIsEditing] = useState(false);
function toggleNameEdit(){
setNameEditing(!nameIsEditing);
}
function toggleCampaignEdit(){
setCampaignIsEditing(!campaignIsEditing);
}
function toggleDescriptionEdit(){
setDescriptionIsEditing(!descriptionIsEditing);
}
我想 re-usable 跨越所有 3 个组件,因为它实际上在做同样的事情。我需要一个函数来处理所有这 3 个,但我真的不确定在哪里或如何执行此操作?我是在减速器中做这个,还是我怎么能把它变成工厂功能?肯定有比我用 {nameIsEditing ? renameComponent : h1
{campaignIsEditing ? renameComponent : h2
{descriptionIsEditing ? renameComponent : h3
您应该简单地创建一个新组件 EditableTitle
。它将处理 isEditing
状态,并执行呈现 read-only 标题或 RenameInput
组件的逻辑。
为了处理标题之间的细微差异,您可以将道具发送到EditableTitle
。例如,您可以发送 component
值来呈现 h1
、h2
或您想要的任何其他组件。