使用 ReactJS 的工作日的多个时间段

IT技术 javascript arrays reactjs react-redux react-hooks
2021-05-24 03:57:40

如果有人可以帮助我优化以下代码。我正在尝试创建一个注册页面,用户可以在其中选择所选日期的可用时间。用户可以选择同一天的多行。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, index) => {
    const { name, 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, { FROM: "", 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>
              &nbsp;&nbsp;&nbsp;
              <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>
              &nbsp;&nbsp;&nbsp;
              <select
                name="FROM"
                value={x.FROM}
                onChange={(e) => handleInputChangeForTuesday(e, i)}
              >
                <option selected hidden>
                  From
                </option>
                {timeList}
              </select>
              &nbsp;&nbsp;&nbsp;
              <select
                name="TO"
                value={x.TO}
                onChange={(e) => handleInputChangeForTuesday(e, i)}
                placeholder="select your Institute"
              >
                <option selected hidden>
                  TO
                </option>
                {timeList}
              </select>
              <div style={{ textAlign: "left", 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>
                )}
1个回答

为了减少冗余,您可以查看重复的代码并更抽象地考虑它。

例如,以下代码抽象地复制了一天的条目,删除了一个元素,并使用当天的新数组更新状态

// 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: "", TO: "" }],
  wednesday: [{ FROM: "", TO: "" }],
  thursday: [{ FROM: "", TO: "" }],
  friday: [{ FROM: "", TO: "" }],
  saturday: [{ FROM: "", TO: "" }],
  sunday: [{ FROM: "", TO: "" }],
});

更新安装效果钩子(这里可能还有改进的余地,因为实际上只是初始化数据;我没有深入研究 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>
        &nbsp;&nbsp;&nbsp;
        <select
          name="TO"
          value={x.TO}
          onChange={(e) => handleInputChangeForDay(e, dayKey, 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>
    );
  });
})}

编辑基于工作日的优化react代码时间可用性