B6: SPA navigation after case creation (useNavigate instead of window.location.href)
B7: stop AdminDashboard refetching the case list on selection change selectedCaseId was both read and written inside the list-loading effect and listed in its deps, causing a second fetch on first render and after every filter reset. Auto-select now uses a functional state update, so the effect no longer depends on selectedCaseId; editForm stays in sync via the existing selectedCase effect.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import Step1Child from "./Step1Child";
|
import Step1Child from "./Step1Child";
|
||||||
import Step2Health from "./Step2Health";
|
import Step2Health from "./Step2Health";
|
||||||
import Step2bPsychotype from "./Step2bPsychotype";
|
import Step2bPsychotype from "./Step2bPsychotype";
|
||||||
@@ -16,6 +17,7 @@ const INITIAL_DATA = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CaseForm = ({ isMobile = false }) => {
|
const CaseForm = ({ isMobile = false }) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [currentStep, setCurrentStep] = useState(1);
|
const [currentStep, setCurrentStep] = useState(1);
|
||||||
const [formData, setFormData] = useState(INITIAL_DATA);
|
const [formData, setFormData] = useState(INITIAL_DATA);
|
||||||
const [errors, setErrors] = useState([]);
|
const [errors, setErrors] = useState([]);
|
||||||
@@ -116,10 +118,11 @@ const CaseForm = ({ isMobile = false }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
|
||||||
// Перенаправляем на страницу анализа с ID карточки
|
// Перенаправляем на страницу анализа с ID карточки.
|
||||||
window.location.href = `/analysis/${result.id}`;
|
// SPA-переход: полная перезагрузка теряла состояние приложения.
|
||||||
|
navigate(`/analysis/${result.id}`);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setErrors([err.message || "Ошибка при отправке данных"]);
|
setErrors([err.message || "Ошибка при отправке данных"]);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -76,11 +76,16 @@ function AdminDashboard() {
|
|||||||
throw new Error(`Не удалось загрузить список кейсов (${response.status})`);
|
throw new Error(`Не удалось загрузить список кейсов (${response.status})`);
|
||||||
}
|
}
|
||||||
const payload = await response.json();
|
const payload = await response.json();
|
||||||
setCases(payload.items || []);
|
const items = payload.items || [];
|
||||||
|
setCases(items);
|
||||||
setTotal(payload.total || 0);
|
setTotal(payload.total || 0);
|
||||||
if ((payload.items || []).length && !selectedCaseId) {
|
// Auto-select the first row only when nothing is selected yet.
|
||||||
setSelectedCaseId(payload.items[0].id);
|
// Functional update so this effect does not have to read (and depend
|
||||||
setEditForm(payload.items[0]);
|
// on) selectedCaseId — depending on it caused a second fetch on first
|
||||||
|
// render and after every filter reset. editForm is kept in sync by the
|
||||||
|
// selectedCase effect below.
|
||||||
|
if (items.length) {
|
||||||
|
setSelectedCaseId((current) => current || items[0].id);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.name !== 'AbortError') {
|
if (err.name !== 'AbortError') {
|
||||||
@@ -93,7 +98,7 @@ function AdminDashboard() {
|
|||||||
|
|
||||||
loadCases();
|
loadCases();
|
||||||
return () => controller.abort();
|
return () => controller.abort();
|
||||||
}, [filters.ageMax, filters.ageMin, filters.status, page, selectedCaseId]);
|
}, [filters.ageMax, filters.ageMin, filters.status, page]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
|||||||
Reference in New Issue
Block a user