Не изменяется состояние массива setState React
Не работает setApplication, в консоль всегда выводит applications.length = 0
// useApplications.js
import { useState, useEffect } from 'react';
const useApplications = () => {
const [applications, setApplications] = useState([]);
const addApplication = (newApplication) => {
console.log('applications.length (before state update):', applications.length);
setApplications(prevApplications => ({
...prevApplications,
...newApplication
})
)
console.log('applications.length (after state update):', applications.length);
}
return {
applications,
addApplication,
};
};
export default useApplications;
Код с использованием useEffect, добавил зависимости:
import { useState, useEffect } from 'react';
const useApplications = () => {
const [applications, setApplications] = useState([]);
const addApplication = (newApplication) => {
console.log('applications.length (before state update):', applications.length);
setApplications((prevApplications) => [
...prevApplications,
newApplication,
]);
};
useEffect(() => {
console.log('applications.length (after state update):', applications.length);
}, [applications]); // Добавил applications как зависимость
return {
applications,
addApplication,
};
};
export default useApplications;
Код App.js:
// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Link, Routes } from 'react-router-dom';
import ApplicationForm from './ApplicationForm';
import ApplicationsList from './ApplicationsList';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Главная</Link>
</li>
<li>
<Link to="/apply">Подать заявку</Link>
</li>
<li>
<Link to="/applications">Заявки</Link>
</li>
</ul>
</nav>
<Routes>
<Route path="/apply" element={<ApplicationForm />} />
<Route path="/applications" element={<ApplicationsList />} />
<Route path="/" element={<Home />} />
</Routes>
</div>
</Router>
);
}
function Home() {
return <h2>Title</h2>;
}
export default App;
index.js:
// index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import './styles.css';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
ApplicationForm.js:
// ApplicationForm.js
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import useApplications from './useApplications';
const ApplicationForm = () => {
const [applicantName, setApplicantName] = useState('');
const [lastName, setLastName] = useState('');
const [patronymic, setPatronymic] = useState('');
const [faculty, setFaculty] = useState('');
const [group, setGroup] = useState('');
const [applicationType, setApplicationType] = useState('scholarship');
const { addApplication } = useApplications();
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
const newApplication = {
applicantName,
lastName,
patronymic,
faculty,
group,
applicationType,
};
addApplication(newApplication);
setApplicantName('');
setLastName('');
setPatronymic('');
setFaculty('');
setGroup('');
setApplicationType('scholarship');
// После сохранения заявки переходим на страницу "Заявок"
navigate('/applications');
};
return (
<form onSubmit={handleSubmit}>
{*Форма заявки*}
<button type="submit">Відправити</button>
</form>
);
};
export default ApplicationForm;
ApplicationList.js:
// ApplicationsList.js
import React, { useState } from 'react';
import useApplications from './useApplications';
const ApplicationsList = () => {
const { applications } = useApplications();
const [selectedApplication, setSelectedApplication] = useState(null);
const handleViewDetails = (application) => {
setSelectedApplication(application);
};
return (
<div>
<h2>Список заявок</h2>
<ul>
{applications.map((app) => (
<li key={app.id}>
<strong>{app.applicantName}</strong>: {app.reason}{' '}
<button onClick={() => handleViewDetails(app)}>Переглянути деталі</button>
</li>
))}
</ul>
{selectedApplication && (
<div>
<h3>Деталі заявки</h3>
<p>
<strong>Ім'я:</strong> {selectedApplication.applicantName}
</p>
<p>
<strong>Прізвище:</strong> {selectedApplication.lastName}
</p>
{/* Другие поля которые нужно отобразить */}
<p>
<strong>Дата та час подання:</strong> {selectedApplication.timestamp.toString()}
</p>
<button onClick={() => setSelectedApplication(null)}>Закрити</button>
</div>
)}
</div>
);
};
export default ApplicationsList;
Ответы (1 шт):
Автор решения: Grundy
→ Ссылка
В первом блоке кода не хватает указания зависимости в useEffect
Если их добавить - console.log вызывается после обновления зависимости:
const {
useState,
useEffect
} = React;
const useApplications = () => {
const [applications, setApplications] = useState([]);
const addApplication = (newApplication) => {
console.log('applications.length (before state update):', applications.length);
setApplications((prevApplications) => [
...prevApplications,
newApplication,
]);
};
useEffect(() => {
console.log('applications.length (after state update):', applications.length);
}, [applications]); // Добавил applications как зависимость
return {
applications,
addApplication,
};
};
const App = () => {
const {
applications,
addApplication
} = useApplications();
return ( < div > {
applications.map((a, i) => < div key = {
i
} > {
i + 1
} - {
a
} < /div>)} <
input type = "button"
value = "add"
onClick = {
() => addApplication(Math.random())
}
/> <
/div>)
}
ReactDOM.createRoot(root).render( < App / > )
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>