“function running before useEffect finishes” 环绕 useEffect 完成之前执行的函数。

huangapple go评论85阅读模式
英文:

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 = () =&gt; {
    let username = &quot;&quot;
    let secret = &quot;&quot;
    useEffect(() =&gt; {
        axios
            .post(&#39;http://localhost:3001/authenticate&#39;)
            .then((response) =&gt; {
                username = response.data.username
                secret = response.data.secret
            })
            .catch((error) =&gt; {
                console.log(error);
            });
    }, []);

    let chatProps = useMultiChatLogic(&#39;xxxxx-xxx-xxx-xxx-xxx&#39;, username, secret);

    return (
        &lt;div style={{ height: &#39;100vh&#39; }}&gt;
            &lt;MultiChatSocket {...chatProps} /&gt;
            &lt;MultiChatWindow {...chatProps} style={{ height: &#39;100vh&#39; }} /&gt;
        &lt;/div&gt;
    );
}

The problem with it is that let chatProps = useMultiChatLogic(&#39;xxxx-xx-x-xx-xxx&#39;, 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 = () =&gt; {
  const [username, setUsername] = useState(&#39;&#39;);
  const [secret, setSecret] = useState(&#39;&#39;);

  useEffect(() =&gt; {
    axios
      .post(&#39;http://localhost:3001/authenticate&#39;)
      .then((response) =&gt; {
        setUsername(response.data.username);
        setSecret(response.data.secret);
      })
      .catch((error) =&gt; {
        console.log(error);
      });
  }, []);

  if (!username || !secret) {
    return &lt;div&gt;Loading...&lt;/div&gt;;
  }

  return &lt;ChatsPage username={username} secret={secret} /&gt;;
};

const ChatsPage = ({username, secret}) =&gt; {
  const chatProps = useMultiChatLogic(&#39;xxxxx-xxx-xxx-xxx-xxx&#39;, username, secret);

  return (
    &lt;div style={{ height: &#39;100vh&#39; }}&gt;
      &lt;MultiChatSocket {...chatProps} /&gt;
      &lt;MultiChatWindow {...chatProps} style={{ height: &#39;100vh&#39; }} /&gt;
    &lt;/div&gt;
  );
};

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 =.

huangapple
  • 本文由 发表于 2023年5月26日 01:26:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76334885.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定