1

我有一个 redux 商店,其中包含一个看起来像的对象

rooms: {
    room01 : { timestamp: 10}
    room02 : { timestamp: 10}
}

当用户单击按钮时,时间戳设置为 10(通过调度)。如果有时间戳,我倒计时到 0,然后react-toast在整个应用程序中使用设置通知。问题是我在 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}
        />
    );

}
4

1 回答 1

1

您可以在其他方法中执行以下操作,但我认为以下是最好的,因为它使 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>);
};
于 2020-08-18T15:49:53.783 回答