Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/web/src/routes/BoardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,27 @@ export function BoardPage() {
const navigate = useNavigate();
const [activeTeamKey, setActiveTeamKey] = useState<string | null>(() => readStoredTeamKey());
const [pendingTeamKey, setPendingTeamKey] = useState<string | null>(null);
const activeTeamKeyRef = useRef(activeTeamKey);
activeTeamKeyRef.current = activeTeamKey;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

避免在渲染过程中直接修改 ref.current。根据 React 官方文档建议,这类副作用操作应放在 useEffectuseLayoutEffect 中,以确保在并发渲染模式下的行为正确性。

  useEffect(() => {
    activeTeamKeyRef.current = activeTeamKey;
  }, [activeTeamKey]);


useEffect(() => {
function handleActiveTeamKeyChange(event: Event) {
const nextTeamKey =
event instanceof CustomEvent && (typeof event.detail === 'string' || event.detail === null)
? (event.detail as string | null)
: readStoredTeamKey();

if (nextTeamKey !== activeTeamKeyRef.current) {
setPendingTeamKey(nextTeamKey);
}
Comment on lines +147 to +149
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

在处理 involute:active-team-key 事件时,如果 nextTeamKey 与当前 activeTeamKey 相同,建议显式将 pendingTeamKey 重置为 null。这可以避免在快速切换团队(例如 A -> B -> A)时,由于 pendingTeamKey 仍停留在旧值('B')而导致组件最终错误地切换到团队 B 的竞态问题。

      setPendingTeamKey(nextTeamKey === activeTeamKeyRef.current ? null : nextTeamKey);

}

window.addEventListener('involute:active-team-key', handleActiveTeamKeyChange as EventListener);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

事件名称 'involute:active-team-key' 在多个组件中硬编码使用。建议将其提取到 utils.ts 中的常量(例如 ACTIVE_TEAM_EVENT),以提高代码的可维护性并减少因拼写错误导致的 Bug。


return () => {
window.removeEventListener('involute:active-team-key', handleActiveTeamKeyChange as EventListener);
};
}, []);
const [isLoadingMoreIssues, setIsLoadingMoreIssues] = useState(false);
const [loadMoreIssuesError, setLoadMoreIssuesError] = useState<string | null>(null);
const queryTeamKey = pendingTeamKey ?? activeTeamKey;
Expand Down
20 changes: 18 additions & 2 deletions packages/web/src/routes/CyclesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMutation, useQuery } from '@apollo/client/react';
import { useRef, useState, useMemo } from 'react';
import { useEffect, useRef, useState, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';

import { BOARD_PAGE_QUERY, CYCLES_QUERY, CYCLE_CREATE_MUTATION, CYCLE_UPDATE_MUTATION, CYCLE_DELETE_MUTATION } from '../board/queries';
Expand Down Expand Up @@ -56,8 +56,24 @@ function isCycleCompleted(cycle: CycleSummary): boolean {

export function CyclesPage() {
const navigate = useNavigate();
const teamKey = readStoredTeamKey();
const [teamKey, setTeamKey] = useState<string | null>(() => readStoredTeamKey());
const dialogRef = useRef<HTMLDialogElement>(null);

useEffect(() => {
function handleActiveTeamKeyChange(event: Event) {
const nextTeamKey =
event instanceof CustomEvent && (typeof event.detail === 'string' || event.detail === null)
? (event.detail as string | null)
: readStoredTeamKey();
setTeamKey(nextTeamKey);
}

window.addEventListener('involute:active-team-key', handleActiveTeamKeyChange as EventListener);

return () => {
window.removeEventListener('involute:active-team-key', handleActiveTeamKeyChange as EventListener);
};
}, []);
const [dialogMode, setDialogMode] = useState<'create' | 'edit'>('create');
const [editingCycleId, setEditingCycleId] = useState<string | null>(null);
const [formName, setFormName] = useState('');
Expand Down
Loading