【问题标题】:How to remove value from state array on click如何在单击时从状态数组中删除值
【发布时间】:2020-08-08 09:17:39
【问题描述】:

目前我正在开发闹钟应用程序,我想这样做,以便您可以添加多个闹钟。每个警报都以 alarms:[] 状态存储在 App.js 文件中。如果添加了闹钟,我想将该闹钟显示为时钟下方的 li 元素,并且我希望能够通过单击 X 图标将其删除。此外,当当前时间 === 为闹钟设置的时间时,Ring.js 组件呈现并且闹钟开始响铃。当闹钟响起时,会有“关闭”按钮。单击关闭按钮后如何从状态数组中删除正在响铃的特定警报?

我尝试在满足条件时将 removeAlarm 函数和警报(这可能有助于确定从数组删除中确定哪个警报)作为该组件的道具。

 function checkTime(){
   if(time.alarms[0]){
     const alarms = time.alarms.map(function(alarm,i){
      if(time.currentHour === alarm.hour && time.currentMinute === alarm.minute && time.currentSecond 
      >= 0){
       return <Ring message={alarm.message} key={i} alarm={alarm} removeAlarm={removeAlarm} />
      }
    })
    return alarms;
  }
}

removeAlarm 功能:

  function removeAlarm(alarm){
   setTime(prevState => ({
    ...prevState,
    alarms:[...prevState.alarms.filter(el => el !== alarm)]
   }))
  }

Ring.js 文件

    let message = props.message;
    function removeAlarm(alarm){
      props.removeAlarm(alarm);
    }

    function turnOff(e,alarm){
      e.preventDefault();
      setShowRing(false);
      removeAlarm(alarm);
    }

    <form>
       <h3>{message}</h3>
       <button onClick={turnOff}>TURN OFF</button>
    </form>

我不知道该怎么做。我不知道如何使用传递的函数或如何在 onClick 函数中确定这是必须发送到 removeAlarm 函数的按钮,映射到状态并删除该特定的。

我注意到的第二个问题是 React Spring Transitions。我在 Ring.js,Alarm.js 中使用它,还想用它来列出 ListAlarms.js 中的活动警报。我使用它的方式与前两个组件完全相同,但对于 ListAlarms.js,它不起作用,我不明白为什么。我的目标是显示那些带有转换的活动警报,而不仅仅是在那里“闪烁”。

谢谢。

CodeSandBox 链接here

【问题讨论】:

    标签: javascript reactjs components react-state


    【解决方案1】:

    可以进行一些更正,但您必须更改过渡

    首先,您需要按 id 过滤列表,以便正确删除警报。

      function removeAlarm(alarm){
       setTime(prevState => ({
        ...prevState,
        alarms:[...prevState.alarms.filter(el => el.id !== alarm.id)]
       }))
      }
    

    其次,我已从您的过渡中删除了 from 属性,因为每个新对象都位于其他对象之上。另外,我使用映射到每个项目的 id 而不是 null 作为键。

    (item) => item.id
    

    最后我更正了 map 函数中的顺序

    {listAlarmTransitions.map(({ item, props, key }) => (
    

    原来如此

      const listAlarmTransitions = useTransition(props.alarms, (item) => item.id, {
        enter: { opacity: 1 },
        leave: { opacity: 0 }
      });
    
      return (
        <ul>
          {listAlarmTransitions.map(({ item, props, key }) => (
            <animated.div key={key} style={props}>
              <li
                key={item.id}
                id={item.id}
                onClick={() => {
                  removeAlarm(item);
                }}
              >
                <FontAwesomeIcon icon={faTimesCircle} className="listIcon" />
                <h3>{item.message}</h3>
                <span>
                  {item.hour}:{item.minute}
                </span>
              </li>
            </animated.div>
          ))}
        </ul>
      );
    

    检查此沙盒 https://codesandbox.io/s/broken-morning-upqwp

    【讨论】:

    • 非常感谢您的时间和回答。它起作用了,现在我知道为这些 li 元素设置动画的问题出在哪里。我没有映射它们,我认为它与其他组件中的动画一样。我可以在 Ring.js 中向您寻求建议吗?我仍然无法弄清楚如何删除正在响铃的特定警报。我的意思是单击“关闭”时从状态中删除。我不知道如何在那里实现使用 id 函数的 ID。 @Apostolos
    • function turnOff(e) { e.preventDefault(); setShowRing(false); removeAlarm(props.alarm); }
    • 更改此功能以使用道具传递的警报,它将起作用。如果我的回答解决了你的问题,请不要忘记接受。它的绿色勾号:)
    • 我不知道我是不是弄错了,但是现在如果我点击关闭,它会删除所有的警报:/这就是我返回到 组件中,我在那个关闭按钮 onclick={turnOff} 和 turnOff 函数看起来像这样: function turnOff(e){e.preventDefault() ;设置显示环(假); removeAlarm(props.alarm)}
    • let id = time.alarms.length &gt; 0 ? Math.max(...time.alarms.map((alarm) =&gt; alarm.id)) + 1 : 1;
    【解决方案2】:

    您正在过滤掉应该按 id 过滤掉的对象/引用。

    您传递的警报参数是一个对象,并且您的警报过滤器数组包含对象,通过查看您的代码,找到一个可以过滤的唯一属性,它应该是 id。

    类似这样的:

      function removeAlarm(alarm){
       setTime(prevState => ({
        ...prevState,
        alarms:[...prevState.alarms.filter(el => el.id !== alarm.id)]
       }))
      }
    

    【讨论】:

      猜你喜欢
      • 2016-07-19
      • 1970-01-01
      • 2016-05-29
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      相关资源
      最近更新 更多