Функция работает до завершения useEffect

У меня есть этот код:

const ChatsPage = () => {
    let username = ""
    let secret = ""
    useEffect(() => {
        axios
            .post('http://localhost:3001/authenticate')
            .then((response) => {
                username = response.data.username
                secret = response.data.secret
            })
            .catch((error) => {
                console.info(error);
            });
    }, []);

    let chatProps = useMultiChatLogic('xxxxx-xxx-xxx-xxx-xxx', username, secret);

    return (
        <div style = {{ height: '100vh' }}>
            <MultiChatSocket {...chatProps} />
            <MultiChatWindow {...chatProps} style = {{ height: '100vh' }} />
        </div>
    );
}

Проблема в том, что let chatProps = useMultiChatLogic('xxxx-xx-x-xx-xxx', username, secret); запускается до завершения useEffect. Я попытался переместить его внутрь .then, где он выдает ошибку ловушек и еще несколько вещей, но ничего не сработало.

Это не проблема, это именно то, чего вы должны ожидать. В этом весь смысл использования useEffect. Вам нужно переместить эти значения в состояние и обработать тот факт, что изначально они не имеют значения.

jonrsharpe 25.05.2023 19:28
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, вам не хватает базового понимания React. Ознакомьтесь с учебным пособием по состоянию, useEffect и потоку управления в целом.

useEffect является асинхронным — обратный вызов выполняется React после первого рендеринга и всякий раз, когда устанавливаются переменные, захваченные в массиве зависимостей. Ваш массив зависимостей пуст, поэтому этот useEffect запускается один раз в жизненном цикле компонента после первого рендеринга.

Я понятия не имею, что такое Multi, но вы можете попробовать что-то вроде этого:

const ChatsPageLoader = () => {
  const [username, setUsername] = useState('');
  const [secret, setSecret] = useState('');

  useEffect(() => {
    axios
      .post('http://localhost:3001/authenticate')
      .then((response) => {
        setUsername(response.data.username);
        setSecret(response.data.secret);
      })
      .catch((error) => {
        console.info(error);
      });
  }, []);

  if (!username || !secret) {
    return <div>Loading...</div>;
  }

  return <ChatsPage username = {username} secret = {secret} />;
};

const ChatsPage = ({username, secret}) => {
  const chatProps = useMultiChatLogic('xxxxx-xxx-xxx-xxx-xxx', username, secret);

  return (
    <div style = {{ height: '100vh' }}>
      <MultiChatSocket {...chatProps} />
      <MultiChatWindow {...chatProps} style = {{ height: '100vh' }} />
    </div>
  );
};

Здесь при первом рендеринге мы знаем, что запрос не завершен, потому что username и secret по-прежнему являются пустыми строками по умолчанию, поэтому мы отображаем сообщение о загрузке. После рендеринга запускается useEffect и запускает запрос.

Через несколько секунд приходит ответ, и мы устанавливаем состояние для username и secret, что запускает другой рендеринг. В этом рендере доступны значения username и secret из ответа (я предполагаю, что они гарантированно будут непустыми строками в ответе), поэтому сообщение о загрузке не отображается. Вместо этого мы визуализируем компонент ChatsPage, который принимает свойства с данными ответа.

Дополнительный компонент необходим, потому что такие хуки, как useMultiChatLogic , должны быть объявлены выше любых условий . Если это не хук, то вызов может происходить в теле функции компонента после if и никаких дополнительных компонентов не требуется.


Золотое правило React заключается в том, что состояние неизменно, поэтому, если какие-либо данные изменяются от одного рендера к другому, это нужно делать через setState, а не =.

спасибо, что поделились этим подробным ответом, очень ценю это. Я не понимал настройку части состояний, а также условный рендеринг страниц. Я очень ценю это, помогая мне учиться!

devdude19289 25.05.2023 19:49

Другие вопросы по теме