英文:
function running before useEffect finishes
问题
I have this code:
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.log(error);
});
}, []);
let chatProps = useMultiChatLogic('xxxxx-xxx-xxx-xxx-xxx', username, secret);
return (
<div style={{ height: '100vh' }}>
<MultiChatSocket {...chatProps} />
<MultiChatWindow {...chatProps} style={{ height: '100vh' }} />
</div>
);
}
The problem with it is that let chatProps = useMultiChatLogic('xxxx-xx-x-xx-xxx', username, secret);
is running before the useEffect
is finished. I have tried to move it inside the .then
, where it gives a hooks error, and a few other things but nothing has worked.
英文:
I have this code:
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.log(error);
});
}, []);
let chatProps = useMultiChatLogic('xxxxx-xxx-xxx-xxx-xxx', username, secret);
return (
<div style={{ height: '100vh' }}>
<MultiChatSocket {...chatProps} />
<MultiChatWindow {...chatProps} style={{ height: '100vh' }} />
</div>
);
}
The problem with it is that let chatProps = useMultiChatLogic('xxxx-xx-x-xx-xxx', username, secret);
is running before the useEffect
is finished. I have tried to move it inside the .then, where it gives a hooks error, and a few other things but nothing has worked.
答案1
得分: 1
I think you're missing a basic understanding of React. Check out a tutorial on state, useEffect
, and control flow in general.
useEffect
is asynchronous--the callback is executed by React after the first render and whenever the variables captured in the dependency array are set. Your dependency array is empty, so this useEffect
runs once in the component's lifecycle, after the first render.
I have no idea what the Multi stuff is, but you could try something like this:
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.log(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>
);
};
Here, on the first render, we know the request hasn't finished because username
and secret
are still the default empty strings, so we render a loading message. After that's rendered, the useEffect
runs and kicks off the request.
After a few moments, the response arrives, and we set state for username
and secret
, which triggers another render. On this render, the username
and secret
values from the response are available (I assume they're guaranteed to be non-empty strings in the response), so the loading message isn't rendered. Instead, we render the ChatsPage
component, which accepts props with the response's data.
The extra component is necessary because hooks like useMultiChatLogic
have to be declared above any conditions. If this isn't a hook, then the call can happen in the component function body after the if
, and no extra component is needed.
The golden rule of React is that state is immutable, so if any data changes from one render to the next, it has to be done through setState
, not =
.
英文:
I think you're missing a basic understanding of React. Check out a tutorial on state, useEffect
and control flow in general.
useEffect
is asynchronous--the callback is executed by React after the first render and whenever the variables captured in the dependency array are set. Your dependency array is empty, so this useEffect
runs once in the component's lifecycle, after the first render.
I have no idea what the Multi stuff is, but you could try something like this:
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.log(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>
);
};
Here, on the first render we know the request hasn't finished because username
and secret
are still the default empty strings, so we render a loading message. After that's rendered, the useEffect
runs and kicks off the request.
After a few moments, the response arrives and we set state for username
and secret
, which triggers another render. On this render, the username
and secret
values from the response are available (I assume they're guaranteed to be nonempty strings in the response), so the loading message isn't rendered. Instead, we render the ChatsPage
component, which accepts props with the response's data.
The extra component is necessary because hooks like useMultiChatLogic
have to be declared above any conditions. If this isn't a hook, then the call can happen in the component function body after the if
and no extra component is needed.
The golden rule of React is that state is immutable, so if any data changes from one render to the next, it has to be done through setState
, not =
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论