问题描述
如果有人可以帮助我优化以下代码。我正在尝试创建一个注册页面,用户可以在其中选择所选日期的时间。用户可以选择在同一天选择多行。.codesandBox的链接为https://codesandbox.io/s/react-hook-helper-availability-0r6bd?file=/src/Second.js。虽然我已经做到了这一点,但是由于我在不同的日子使用相同的代码,因此可以进一步对其进行优化。我正在重用相同的代码。我只添加了星期一和星期二,以防万一我不得不使用星期一到星期六,那么我将不得不重复相同的代码,但在几个字段中进行更改。
const [monday,setMonday] = useState([{ FROM: "",TO: "" }]);
const [tuesday,setTuesday] = useState([{ FROM: "",TO: "" }]);
const [time,setTime] = useState([
{ Id: "00:30",value: "00:30" },{ Id: "01:00",value: "01:00" },{ Id: "01:30",value: "01:30" },{ Id: "02:00",value: "02:00" },......
let timeList =
time.length > 0 &&
time.map((item,i) => {
return (
<>
<option key={item.Id} value={item.id}>
{item.value}
</option>
</>
);
},this);
const handleInputChangeForMonday = (e,index) => {
const { name,value } = e.target;
const list = [...monday];
list[index][name] = value;
setMonday(list);
};
// handle click event of the Remove button
const handleRemoveClickForMonday = (index) => {
const list = [...monday];
list.splice(index,1);
setMonday(list);
};
// handle click event of the Add button
const handleAddClickForMonday = () => {
setMonday([...monday,{ FROM: "",TO: "" }]);
};
// handle input change
const handleInputChangeForTuesday = (e,value } = e.target;
const list = [...tuesday];
list[index][name] = value;
setTuesday(list);
};
// handle click event of the Remove button
const handleRemoveClickForTuesday = (index) => {
const list = [...tuesday];
list.splice(index,1);
setTuesday(list);
};
// handle click event of the Add button
const handleAddClickForTuesday = () => {
setTuesday([...tuesday,TO: "" }]);
};
<form onSubmit={onSubmit}>
{monday.map((x,i) => {
return (
<React.Fragment>
<select
name="FROM"
value={x.FROM}
onChange={(e) => handleInputChangeForMonday(e,i)}
>
<option selected hidden>
From
</option>
{timeList}
</select>
<select
name="TO"
value={x.TO}
onChange={(e) => handleInputChangeForMonday(e,i)}
placeholder="select your Institute"
>
<option selected hidden>
TO
</option>
{timeList}
</select>
<div style={{ textAlign: "left",width: "84%" }}>
{monday.length !== 1 && (
<label
as="a"
onClick={() => handleRemoveClickForMonday(i)}
style={{ marginRight: "10px" }}
>
remove
</label>
)}
{monday.length - 1 === i && (
<button
type="button"
as="a"
onClick={handleAddClickForMonday}
style={{ marginRight: "10px" }}
>
add
</button>
)}
</div>
</React.Fragment>
);
})}
<br />
<br />
{tuesday.map((x,i) => {
return (
<React.Fragment>
<select
name="FROM"
value={x.FROM}
onChange={(e) => handleInputChangeForTuesday(e,i)}
>
<option selected hidden>
From
</option>
{timeList}
</select>
<select
name="TO"
value={x.TO}
onChange={(e) => handleInputChangeForTuesday(e,width: "84%" }}>
{tuesday.length !== 1 && (
<label
as="a"
onClick={() => handleRemoveClickForTuesday(i)}
style={{ marginRight: "10px" }}
>
remove
</label>
)}
{tuesday.length - 1 === i && (
<button
type="button"
as="a"
onClick={handleAddClickForTuesday}
style={{ marginRight: "10px" }}
>
add
</button>
)}
解决方法
为减少冗余,您可以查看重复的代码,然后更抽象地考虑它。
例如,以下代码抽象地复制一天的条目,删除元素,并使用该天的新数组更新状态
// handle click event of the Remove button
const handleRemoveClickForMonday = (index) => {
const list = [...monday];
list.splice(index,1);
setMonday(list);
};
现在,您可以抽象地在任何一天进行操作,请考虑一个数据结构,该数据结构适合查找特定的一天来进行操作,例如地图。在javascript中,通常使用对象({}
)作为键值对的映射。
使用日期键将状态转换为对象
const [days,setDays] = useState({
monday: [{ FROM: "",TO: "" }],tuesday: [{ FROM: "",wednesday: [{ FROM: "",thursday: [{ FROM: "",friday: [{ FROM: "",saturday: [{ FROM: "",sunday: [{ FROM: "",});
更新安装效果钩子(在这里也可能有改进的空间,因为实际上只是在初始化数据;我没有深入研究AVAILABILITY_XXX是什么)
useEffect(() => {
if (AVAILABILITY_MONDAY.length > 0)
setDays((days) => ({
...days,monday: AVAILABILITY_MONDAY
}));
if (AVAILABILITY_TUESDAY.length > 0)
setDays((days) => ({
...days,tuesday: AVAILABILITY_TUESDAY
}));
// etc for each day of the week
},[]);
转换提交处理程序以访问新的状态形状
const onSubmit = (data) => {
const e = {
target: {
name: "AVAILABILITY_MONDAY",value: days.monday
}
};
const f = {
target: {
name: "AVAILABILITY_TUESDAY",value: days.tuesday
}
};
// etc for each day
setForm(e);
setForm(f);
// etc
navigation.next();
};
将处理程序转换为一天密钥
// handle input change
const handleInputChangeForDay = (e,day,index) => {
const { name,value } = e.target;
const list = [...days[day]];
list[index][name] = value;
setDays((days) => ({
...days,[day]: list
}));
};
// handle click event of the Remove button
const handleRemoveClickForDay = (day,index) => {
const list = [...days[day]];
list.splice(index,1);
setDays((days) => ({
...days,[day]: list
}));
};
// handle click event of the Add button
const handleAddClickForDay = (day) => () => {
setDays((days) => ({
...days,[day]: [...days[day],{ FROM: "",TO: "" }]
}));
};
每天从状态创建一个键-值对数组并进行映射
{Object.entries(days).map(([dayKey,day]) => {
return day.map((x,i) => {
return (
<React.Fragment>
Day: {dayKey}
<select
name="FROM"
value={x.FROM}
onChange={(e) => handleInputChangeForDay(e,dayKey,i)}
>
<option selected hidden>
From
</option>
{timeList}
</select>
<select
name="TO"
value={x.TO}
onChange={(e) => handleInputChangeForDay(e,i)}
placeholder="select your Institute"
>
<option selected hidden>
TO
</option>
{timeList}
</select>
<div style={{ textAlign: "left",width: "84%" }}>
{day.length !== 1 && (
<label
as="a"
onClick={() => handleRemoveClickForDay(dayKey,i)}
style={{ marginRight: "10px" }}
>
remove
</label>
)}
{day.length - 1 === i && (
<button
type="button"
as="a"
onClick={handleAddClickForDay(dayKey)}
style={{ marginRight: "10px" }}
>
add
</button>
)}
</div>
</React.Fragment>
);
});
})}