javascript 函数在useEffect完成之前运行

np8igboo  于 2023-05-27  发布在  Java
关注(0)|答案(1)|浏览(155)

我有这个代码:

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>
    );
}

它的问题是let chatProps = useMultiChatLogic('xxxx-xx-x-xx-xxx', username, secret);useEffect完成之前就已经运行了。我试着把它移到.then里面,在那里它给出了一个钩子错误,还有其他一些东西,但都没有起作用。

sqxo8psd

sqxo8psd1#

我认为你缺少对React的基本理解。查看关于状态、useEffect和控制流的一般教程。
useEffect是异步的--回调函数在第一次渲染之后以及在依赖数组中捕获的变量被设置时由React执行。您的依赖项数组是空的,因此这个useEffect在组件的生命周期中运行一次,在第一次呈现之后。
我不知道什么是多的东西,但你可以尝试这样的东西:

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>
  );
};

这里,在第一次呈现时,我们知道请求还没有完成,因为usernamesecret仍然是默认的空字符串,所以我们呈现了一条加载消息。渲染完成后,useEffect运行并启动请求。
过了一会儿,响应到达,我们为usernamesecret设置状态,这会触发另一个渲染。在这个呈现中,来自响应的usernamesecret值是可用的(我假设它们在响应中保证是非空字符串),因此不会呈现加载消息。相反,我们呈现ChatsPage组件,它接受带有响应数据的props。
额外的组件是必要的,因为挂钩像useMultiChatLogichave to be declared above any conditions。如果这不是一个钩子,那么调用可以发生在if之后的组件函数体中,不需要额外的组件。
React的黄金法则是状态是不可变的,所以如果任何数据从一个渲染器到下一个渲染器发生变化,它必须通过setState完成,而不是=

相关问题