优化ProfileModules组件中的状态管理,使用选择器函数订阅匹配的客服对象,避免不必要的重新渲染。同时在DetailValue组件中引入useRef进行深度比较,确保只有在值真正变化时才更新编辑状态。

This commit is contained in:
超级老白兔
2025-11-20 16:13:57 +08:00
parent 16a8656b49
commit 84ced0c32a
2 changed files with 57 additions and 10 deletions

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useState, useEffect } from "react";
import React, { useCallback, useState, useEffect, useRef } from "react";
import { Input, message } from "antd";
import { Button } from "antd-mobile";
import { EditOutlined } from "@ant-design/icons";
@@ -56,8 +56,32 @@ const DetailValue: React.FC<DetailValueProps> = ({
useState<Record<string, string>>(value);
const [changedKeys, setChangedKeys] = useState<string[]>([]);
// 使用 useRef 存储上一次的 value用于深度比较
const prevValueRef = useRef<Record<string, string>>(value);
// 深度比较函数:比较两个对象的值是否真的变化了
const isValueChanged = useCallback(
(prev: Record<string, string>, next: Record<string, string>) => {
const allKeys = new Set([...Object.keys(prev), ...Object.keys(next)]);
for (const key of allKeys) {
if (prev[key] !== next[key]) {
return true;
}
}
return false;
},
[],
);
// 当外部value变化时更新内部状态
// 优化:只有当值真正变化时才重置编辑状态,避免因对象引用变化导致编辑状态丢失
useEffect(() => {
// 深度比较,只有当值真正变化时才更新
if (!isValueChanged(prevValueRef.current, value)) {
return;
}
// 只有在值真正变化时才更新状态
setFieldValues(value);
setOriginalValues(value);
setChangedKeys([]);
@@ -67,7 +91,10 @@ const DetailValue: React.FC<DetailValueProps> = ({
newEditingFields[field.key] = false;
});
setEditingFields(newEditingFields);
}, [value, fields]);
// 更新 ref
prevValueRef.current = value;
}, [value, fields, isValueChanged]);
const handleFieldChange = useCallback(
(fieldKey: string, nextVal: string) => {

View File

@@ -210,14 +210,34 @@ const Person: React.FC<PersonProps> = ({ contract }) => {
// 构建联系人或群聊详细信息
const customerList = useCustomerStore(state => state.customerList);
const kfSelectedUser = useMemo(() => {
if (!contract.wechatAccountId) return null;
const matchedCustomer = customerList.find(
customer => customer.id === contract.wechatAccountId,
);
return matchedCustomer || null;
}, [customerList, contract.wechatAccountId]);
// 优化:使用选择器函数直接订阅匹配的客服对象,避免订阅整个 customerList
// 添加相等性比较,只有当匹配的客服对象或其 labels 真正变化时才触发重新渲染
const kfSelectedUser = useCustomerStore(
state => {
if (!contract.wechatAccountId) return null;
return (
state.customerList.find(
customer => customer.id === contract.wechatAccountId,
) || null
);
},
(prev, next) => {
// 如果都是 null认为相等
if (!prev && !next) return true;
// 如果一个是 null 另一个不是,认为不相等
if (!prev || !next) return false;
// 比较关键字段id 和 labels因为 useEffect 中使用了 labels
if (prev.id !== next.id) return false;
// 比较 labels 数组是否真的变化了
const prevLabels = prev.labels || [];
const nextLabels = next.labels || [];
if (prevLabels.length !== nextLabels.length) return false;
// 深度比较 labels 数组内容(先复制再排序,避免修改原数组)
const prevLabelsStr = JSON.stringify([...prevLabels].sort());
const nextLabelsStr = JSON.stringify([...nextLabels].sort());
return prevLabelsStr === nextLabelsStr;
},
);
// 不再需要从useContactStore获取getContactsByCustomer