У меня есть этот код:
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, где он выдает ошибку ловушек и еще несколько вещей, но ничего не сработало.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я думаю, вам не хватает базового понимания 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, а не =.
спасибо, что поделились этим подробным ответом, очень ценю это. Я не понимал настройку части состояний, а также условный рендеринг страниц. Я очень ценю это, помогая мне учиться!
Это не проблема, это именно то, чего вы должны ожидать. В этом весь смысл использования
useEffect. Вам нужно переместить эти значения в состояние и обработать тот факт, что изначально они не имеют значения.