微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何与setInterval一起触发事件? JavaScript / React-toastify

如何解决如何与setInterval一起触发事件? JavaScript / React-toastify

我有一个redux存储,其中包含一个看起来像

的对象
rooms: {
    room01 : { timestamp: 10}
    room02 : { timestamp: 10}
}

用户单击按钮时,时间戳设置为10(通过调度)。如果有时间戳,我会倒数为0,然后在整个应用中使用react-toast设置一个Notification。 问题是我在Notification组件上没有roomId可用,因为必须将Notification组件放置在应用程序的根目录下,否则它将被卸载并且我的Notification()逻辑不起作用。 (我可以在Notification或App中访问房间,但是它以数组形式存在,例如['room01','room02'],该数组也在redux中,但是我如何选择两个房间并访问其时间戳并运行该函数来倒计时?)。

基本上,我需要检查每个房间的redux存储区中是否有时间戳,如果有,则倒计数为0并显示带有roomId的通知。导航到其他页面时,通知/设置间隔应该可以工作。

My app component 

import React from 'react';
import { Route,Switch,browserRouter } from 'react-router-dom';

import Home from './Home';
import 'react-toastify/dist/ReactToastify.css';
import Notification from '../features/seclusion/Notification';

const App = () => {
    return (
        <div>
            <Notification /> // if I pass in room id like so roomId={'room02'} I cant get it to work for one room
            <browserRouter>
                <Switch>
                    <Route exact path="/room/:id" component={Room} />
                    <Route exact path="/" component={Home} />
                </Switch>
            </browserRouter>
        </div>);
};

export default App;

import React,{ useState,useEffect } from 'react';
import { useSelector } from 'react-redux';
import 'react-toastify/dist/ReactToastify.css';
import { ToastContainer,toast,Slide } from 'react-toastify';
import moment from 'moment';

export default function Notification() {
    
    const timestamp =  useSelector(state =>  state.rooms); // need to get timestamp  for room01 and room02 
    
    const [timestamp,setTimestamp] = useState(null);
    const [timerId,setTimerId] = useState(null);

    const notify = () => {
        toast(<div>alert</div>,{
                position: "top-center",});
    }; 

    useEffect(() => {
        if (timestamp) {
            const id = setInterval(() => {
               setTimestamp((timestamp) =>  timestamp - 1)
            },1000)

            setTimerId(id);

        }
        return () => {
            clearInterval(timerId);
        };
    },[timestamp]);

    useEffect(() => {
        if(timestamp === 0){
            notify();
            clearInterval(timerId); 
        }
    },[timestamp])

    return (
        <ToastContainer
            newestOnTop={true}
            transition={Slide}
            autoClose={false}
        />
    );

}

解决方法

您可以在其他方法中执行以下操作,但是我认为以下操作是最好的,因为它使Notification组件更可重用,并且可以更好地利用职责分离,使代码更易于阅读,并且大多数重要的是要与React的声明式思维保持一致。

const App = () => {
    const rooms = state.rooms // this is not redux syntax but i will leave that to you
    return (
        <div>
            {Object.entries(rooms).map(([roomId,roomDetails]) => {
              const {timestamp} =  roomDetails;
              // Obviously you now need to modify your Notification component to handle these props
              return <Notification 
                      timestamp={timestamp} 
                      roomId={roomId} // actually its better to create the Notification component without the roomId prop and use the roomId to induce the message prop,this makes Notification component more reusable across other components 
                      key={`${roomId}-${timestamp}`} 
                      message="You might send message here instead of doing that inside the Notification component" 
                    />
                    // You might be interested to rename Notification to DelayedNotification or something else 
            }}
            <BrowserRouter>
                <Switch>
                    <Route exact path="/room/:id" component={Room} />
                    <Route exact path="/" component={Home} />
                </Switch>
            </BrowserRouter>
        </div>);
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。