我的 useEffect
中有一个简单的 Task
钩子:
const TaskAD = ({ match }: TaskADProps) => {
const { taskName } = match.params;
const [task, setTask] = useState<TaskData | null>(null);
const [loading, setLoading] = useState(true);
const authCommunicator = authRequest();
useEffect(() => {
const getTask = async () => {
const taskData = await authCommunicator
.get(`/task/${taskName}`)
.then((response) => response.data);
setTask(taskData);
setLoading(false);
};
getTask();
}, []);
if (loading || task == null) {
return <Spinner centered />;
}
const updateDescription = async (content: string): Promise<boolean> => {
const r = await authCommunicator
.patch(`/task/${task.name}/`, {
description: content,
})
.then((response) => {
console.log("Setting Task data!");
setTask(response.data);
return true;
})
.catch(() => false);
return r;
};
return (
<ProjectEntity name={taskName}>
<Space direction="vertical" size="small" style={{ width: "100%" }}>
<StatusRow status="Open" />
<TaskDetails task={task} />
<Description content={task.description} onSubmit={updateDescription} />
<Title level={2}>Subtasks:</Title>
<Table dataSource={dataSource} columns={columns} />
</Space>
</ProjectEntity>
);
};
Task
对象包含描述。描述是另一个带有文本区域的组件。这个想法是:当用户改变子组件中的描述时,子组件有一个函数(通过 props 传递)来更新描述。
所以我通过 props 将 updateDescription
传递给我的子组件 (Description
)。 useEffect
和 updateDescription
都在我的 Task
组件中,Description
组件基本上是无状态的。会发生什么:
setTask
task
变量通过 Description
的 Task
中的 props 传递给 render
,因此它们都会更新,因为父 Task
的状态已更改唯一的问题是,虽然它可以工作,但是当我这样做时,我可以在控制台中看到:
Setting Task data!
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
(我添加了 console.log
只是为了看看它何时发生)。
所以我想问一下这是我在 useEffect
之外进行异步调用的问题还是其他原因?
@Edit Description
代码(我删除了所有不必要的垃圾):
interface DescriptionProps {
content: string;
onSubmit?: (content: string) => Promise<boolean>;
title?: string;
rows?: number;
}
const Description = (props: DescriptionProps) => {
const { content, onSubmit, title, rows } = props;
const [descriptionContent, setDescriptionContent] = useState(content);
const [expanded, setExpanded] = useState(true);
const [editMode, setEditMode] = useState(false);
const [descriptionChanged, setDescriptionChanged] = useState(false);
const editable = onSubmit !== undefined;
const resetDescription = () => {
setDescriptionContent(content);
setDescriptionChanged(false);
};
const changeDescription = (value: string) => {
setDescriptionContent(value);
setDescriptionChanged(true);
};
const descriptionTitle = (
<>
<S.DescriptionTitle>{title}</S.DescriptionTitle>
</>
);
return (
<Collapse
defaultActiveKey={["desc"]}
expandIcon={S.ExpandIcon}
onChange={() => setExpanded(!expanded)}
>
<S.DescriptionHeader header={descriptionTitle} key="desc">
<S.DescriptionContent
onChange={(event): void => changeDescription(event.target.value)}
/>
{descriptionChanged && onSubmit !== undefined ? (
<S.DescriptionEditActions>
<Space size="middle">
<S.SaveIcon
onClick={async () => {
setDescriptionChanged(!(await onSubmit(descriptionContent)));
}}
/>
<S.CancelIcon onClick={() => resetDescription()} />
</Space>
</S.DescriptionEditActions>
) : null}
</S.DescriptionHeader>
</Collapse>
);
};
@Edit2
有趣的是,将此添加到我的 Description
中可以解决问题:
useEffect(
() => () => {
setDescriptionContent("");
},
[content]
);
谁能解释一下为什么?