SubscribeUserEvents.jsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import React from "react";
  2. import { useSetRecoilState, useRecoilState } from "recoil";
  3. import { userAtom, usersAtom } from "./atoms";
  4. import debounce from "lodash.debounce";
  5. import useC2C from "../hooks/useC2C";
  6. const SubscribeUserEvents = () => {
  7. const usersRef = React.useRef([]);
  8. const setUsers = useSetRecoilState(usersAtom);
  9. const [currentUser, setCurrentUserState] = useRecoilState(userAtom);
  10. const { c2c, isMaster } = useC2C("room");
  11. React.useEffect(() => {
  12. setCurrentUserState((prevUser) => ({
  13. ...prevUser,
  14. id: c2c.userId,
  15. }));
  16. }, [c2c.userId, setCurrentUserState]);
  17. React.useEffect(() => {
  18. if (!isMaster) {
  19. const onGetUserList = (userList) => {
  20. usersRef.current = userList;
  21. setUsers(userList);
  22. };
  23. c2c.call("getUserList").then(onGetUserList, () => {
  24. // retry later
  25. setTimeout(() => {
  26. c2c
  27. .call("getUserList")
  28. .then(onGetUserList, (error) => console.log(error));
  29. }, 1000);
  30. });
  31. }
  32. }, [c2c, isMaster, setUsers]);
  33. // eslint-disable-next-line react-hooks/exhaustive-deps
  34. const debouncedEmitUpdateUser = React.useCallback(
  35. debounce((newUser) => {
  36. c2c.publish("userUpdate", newUser, true);
  37. }, 500),
  38. [c2c]
  39. );
  40. React.useEffect(() => {
  41. if (currentUser && currentUser.id) {
  42. debouncedEmitUpdateUser(currentUser);
  43. }
  44. }, [currentUser, debouncedEmitUpdateUser]);
  45. React.useEffect(() => {
  46. const unsub = [];
  47. if (isMaster) {
  48. c2c
  49. .register("getUserList", () => {
  50. return usersRef.current;
  51. })
  52. .then((unregister) => {
  53. unsub.push(unregister);
  54. });
  55. unsub.push(
  56. c2c.subscribe("userUpdate", (user) => {
  57. if (usersRef.current.find((u) => u.id === user.id)) {
  58. const newUsers = usersRef.current.map((u) =>
  59. u.id === user.id ? user : u
  60. );
  61. usersRef.current = newUsers;
  62. } else {
  63. const newUsers = [...usersRef.current, user];
  64. usersRef.current = newUsers;
  65. }
  66. setUsers(usersRef.current);
  67. c2c.publish("updateUserList", usersRef.current);
  68. })
  69. );
  70. }
  71. unsub.push(
  72. c2c.subscribe("userLeave", (userId) => {
  73. usersRef.current = usersRef.current.filter(({ id }) => id !== userId);
  74. setUsers(usersRef.current);
  75. if (isMaster) {
  76. c2c.publish("updateUserList", usersRef.current);
  77. }
  78. })
  79. );
  80. unsub.push(
  81. c2c.subscribe("updateUserList", (newList) => {
  82. usersRef.current = newList;
  83. setUsers(usersRef.current);
  84. })
  85. );
  86. return () => {
  87. unsub.forEach((u) => u());
  88. };
  89. }, [c2c, isMaster, setUsers]);
  90. return null;
  91. };
  92. export default SubscribeUserEvents;