Reactjs 使用带有React-useEffect挂钩的侦听器

Reactjs 使用带有React-useEffect挂钩的侦听器,reactjs,react-native,react-hooks,Reactjs,React Native,React Hooks,我有一个useEffect挂钩,可以在我的应用程序中处理在线用户 const [users, setUsers] = useState({} as Users); useEffect(() => { const handleOnlineStatus = (onlineStatus: Array<OnlineStatus>) => { const usersCopy = {...users}; if (onlineStatus.length ===

我有一个useEffect挂钩,可以在我的应用程序中处理在线用户

const [users, setUsers] = useState({} as Users);

useEffect(() => {
    const handleOnlineStatus = (onlineStatus: Array<OnlineStatus>) => {
    const usersCopy = {...users};
    if (onlineStatus.length === 0) {
        return;
    }


    onlineStatus.forEach((status: OnlineStatus) => {
        const uid = status.userId;

        if (!uid) {
        return;
        }

        if (uid in usersCopy) {
        const lastStatus = usersCopy[uid].status;
        if (lastStatus !== usersCopy) {
            usersCopy[uid].status = status.value;

            setUsers({...usersCopy});
        }
        }
    });
    };
    subscribeToIsOnline((onlineStatus: Array<OnlineStatus>) => {
        handleOnlineStatus(onlineStatus);
    });
});

public handleOnlineStatus(callback: (users: Array<OnlineStatus>) => void) {
    this.logDebug('subscribeToOnlineStatusIndication');

    try {
      return ChatClient.addListener('OnlineStatusIndication', (users: Array<OnlineStatus>) => callback(users));
    } catch (e) {
      this.logError(e);
    }
}
const[users,setUsers]=useState({}作为用户);
useffect(()=>{
const handleOnlineStatus=(onlineStatus:Array)=>{
const usersCopy={…users};
如果(onlineStatus.length==0){
返回;
}
onlineStatus.forEach((状态:onlineStatus)=>{
const uid=status.userId;
如果(!uid){
返回;
}
if(userscope中的uid){
const lastStatus=UserScope[uid]。状态;
if(lastStatus!==用户状态){
UserScope[uid]。状态=状态。值;
setUsers({…usersCopy});
}
}
});
};
subscribeToIsOnline((onlineStatus:Array)=>{
HandlineStatus(联机状态);
});
});
公共handleOnlineStatus(回调:(用户:数组)=>void){
this.logDebug('subscribeToOnlineStatusIndication');
试一试{
返回ChatClient.addListener('OnlineStatusIndication',(用户:数组)=>回调(用户));
}捕获(e){
这是logError(e);
}
}
但使用此代码,每次用户重新联机时都会重新创建侦听器。 所以我更新了代码如下:

useEffect(() => {
    // ... same code
}, []); // <--
useffect(()=>{
//…相同的代码

}, []); // 我认为您的思路是正确的,但是您已经在回调中包含了初始的
用户
状态对象(
{}
)。换句话说,它是一个过时的存储模块,因此您总是从初始渲染复制
用户
状态

您还使用
usersCopy[uid]改变状态

使用功能状态更新访问您可以从中进行更新的上一个状态

const [users, setUsers] = useState({} as Users);

useEffect(() => {
  const handleOnlineStatus = (onlineStatus: Array<OnlineStatus>) => {
    if (!onlineStatus.length) {
      return;
    }

    onlineStatus.forEach((status: OnlineStatus) => {
      const uid = status.userId;

      if (!uid) {
        return;
      }

      setUsers(users => {
        if (uid in users) {
          const lastStatus = users[uid].status;
          if (lastStatus !== users) {
            return {
              ...users, // <-- shallow copy into new state object
              [uid]: {
                ...users[uid], // <-- shallow copy old user object
                status: status.value, // <-- update property
              }
            };
          }
        }
        return users; // <-- old state
      });
    });
  };

  subscribeToIsOnline((onlineStatus: Array<OnlineStatus>) => {
    handleOnlineStatus(onlineStatus);
  });
}, []); // <-- empty dependency array to run effect once
const[users,setUsers]=useState({}作为用户);
useffect(()=>{
const handleOnlineStatus=(onlineStatus:Array)=>{
如果(!onlineStatus.length){
返回;
}
onlineStatus.forEach((状态:onlineStatus)=>{
const uid=status.userId;
如果(!uid){
返回;
}
设置用户(用户=>{
如果(用户中的uid){
const lastStatus=用户[uid]。状态;
if(lastStatus!==用户){
返回{

…用户,//subscribeToIsOnline
是否返回一些清理功能,如
unsubscribe
?不,这是一个简单的addListener,我更新了codeAh bummer,如果它更新了会更容易。我们必须解决这个问题。也许我可以尝试添加一个,ChatClient是我们的代码。为什么它很重要?订阅者应该只实例化一次对吗?好吧,你的
用户
状态有一个陈旧的外壳,如果
subscribeToIsOnline
返回了一个清理函数,你可以简单地使用
用户
作为
使用效果
依赖项,并在
用户
状态更新时返回清理函数删除侦听器。另一种方法包括它将处理程序拆分为自己的记忆回调或重写逻辑,以便使用功能状态更新。UserScope中的
uid
检查有点搞砸了。谢谢Drew。您的代码正在工作,最重要的是我了解发生了什么!