【问题标题】:indexOf() not working as expected, function keeps adding duplicates - ReactindexOf() 没有按预期工作,函数不断添加重复项 - React
【发布时间】:2021-03-08 16:05:30
【问题描述】:
const [dates, setDates] = useState([]);

const handleClick = (day) => {
  let newArray = [...dates];
  let indexItem = newArray.indexOf(day);
  indexItem === -1 ? newArray.push(day) : newArray.splice(indexItem, 1);
  setDates(newArray);
};

useEffect(() => {
  console.log(dates);
}, [dates]);

return(
  <DayPicker selectedDays={dates} onDayClick={handleClick} />
)

是否可以更新我的代码以使状态仅包含单击一次并在单击两次时删除的日期?

有点能够在状态中切换日期。

我的函数只在元素添加 2 次后才移除元素,因此 atm 无法从数组中移除重复元素。

handleClick 中的 day 参数以字符串形式返回值,例如:

Fri Mar 05 2021 12:00:00 GMT+0100 (Central European Standard Time)

当 i console.log() 在浏览器中约会时,它是这样的:

0: Wed Mar 03 2021 12:00:00 GMT+0100 (Central European Standard Time) {}
1: Wed Mar 10 2021 12:00:00 GMT+0100 (Central European Standard Time) {}
2: Wed Mar 17 2021 12:00:00 GMT+0100 (Central European Standard Time) {}
3: Wed Mar 03 2021 12:00:00 GMT+0100 (Central European Standard Time) {}
4: Wed Mar 10 2021 12:00:00 GMT+0100 (Central European Standard Time) {}
5: Wed Mar 17 2021 12:00:00 GMT+0100 (Central European Standard Time) {}

你可以看到重复的,如果我再次点击同一天,结果会是

0: Wed Mar 03 2021 12:00:00 GMT+0100 (Central European Standard Time) {}
1: Wed Mar 10 2021 12:00:00 GMT+0100 (Central European Standard Time) {}
2: Wed Mar 17 2021 12:00:00 GMT+0100 (Central European Standard Time) {}

而不是

[]

提前致谢!

【问题讨论】:

  • 这是模块react-day-picker.js.org。但是function 中的day 参数返回一个string,正如上面提到的那样:)
  • @CertainPerformance 我更新了我的问题,提供了有关控制台输出的更多详细信息,如果您可以看一下 :)
  • 您调用array .splice() 并忽略返回值。所以你永远只添加元素。每当我使用一个我很容易忘记细节的函数时,我就养成了访问mdn docu 的习惯。

标签: reactjs react-hooks use-effect use-state


【解决方案1】:

问题在于库传递给单击处理程序的参数是日期,而不是字符串,因此indexOf 不起作用 - 不同的对象彼此不是===,即使它们包含相同的值。因此,找到的索引始终为 -1,并且重复的对象被添加到状态中。

我会创建一个 timestamps(数字)数组,以便轻松检测到重复项:

const [timestamps, setTimestamps] = React.useState([]);

const handleClick = (clickedDate) => {
    const clickedTimestamp = clickedDate.getTime();
    const index = timestamps.indexOf(clickedTimestamp);
    if (index === -1) {
        setTimestamps([...timestamps, clickedTimestamp]);
    } else {
        setTimestamps(
            timestamps.filter((_, i) => i !== index)
        );
    }
};
<DayPicker
    selectedDays={timestamps.map(t => new Date(t))}
    onDayClick={handleClick}
/>

【讨论】:

  • 惊人的答案,非常感谢您的调查!我对这种方法的唯一问题是在 mongoDB 的 post request 阶段。 timestamps (numbers) 的数组未添加到数据库中。 sameHanwar 的方法将numbers 再次转换为strings。当然,我也可以使用您的解决方案单独执行此操作。再次感谢!
【解决方案2】:

我认为更合适的方法是将所选日期转换为时间戳格式,然后将其与状态进行比较。

const [dates, setDates] = useState([]);

  const handleClick = (day) => {
    let currentDay = new Date(day).getTime();
    let newArray = [...dates];
    let indexItem = newArray.indexOf(currentDay);

    indexItem === -1 ? newArray.push(currentDay) : newArray.splice(indexItem, 1);
    setDates(newArray);
  };

  useEffect(() => {
    console.log(dates);
  }, [dates]);

  const selectedDates = dates && dates.map((date) => new Date(date));

  return <DayPicker selectedDays={selectedDates} onDayClick={handleClick} />;

【讨论】:

  • 感谢您的调查!像魅力一样工作,这样我可以立即将timestamps 作为strings 发布到mongoDB。再次感谢您的时间:)
猜你喜欢
  • 1970-01-01
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
  • 2014-12-17
  • 2012-11-01
  • 2011-12-01
  • 1970-01-01
  • 2020-12-10
相关资源
最近更新 更多