Не изменяется состояние массива 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>

→ Ссылка