useCallBack 执行两次 [英] useCallBack executes twice

查看:41
本文介绍了useCallBack 执行两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么 useCallback 钩子会执行两次?我收到一条警告,建议我使用 useCallback,所以我正在尝试这样做.根据我的理解,useCallback 只会在我们传递给数组的对象更新时执行.所以我的目标是让 websocket 在加载令牌后进行连接.它主要"有效;套接字连接两次,回调运行两次.

const setupSocket = () =>{如果(令牌&& !socket&&经过身份验证){console.log(token, authentication, socket === null);const newSocket = io(ENDPOINT, {询问: {令牌,},});newSocket.on(断开连接", () => {设置套接字(空);setTimeout(setupSocket, 3000);});newSocket.on("connect", () => {console.log(成功,连接到套接字");});设置套接字(新套接字);}};useCallback(setupSocket(), [token]);

App.js

import React, { useEffect, useState, useCallback } from react";import { BrowserRouter as Router, Route, Switch } from react-router-dom";导入./App.css";//页面从./pages/home.jsx"导入主页;从./pages/login/login.container"导入 LoginContainer;从./pages/signup"导入注册;从./pages/post-detail/post-detail.container.js"导入 PostDetailContainer;从jwt-decode"导入 jwtDecode;从./pages/profile/profile.container"导入 ProfileContainer;从./pages/about/about.container"导入AboutContainer;//组件从./components/Navbar"导入导航栏;从./utils/AuthRoute"导入 AuthRoute;//还原从react-redux"导入{连接};//套接字IO从socket.io-client"导入io;//动作进口 {清除用户数据,getUserFromToken,设置身份验证,} 来自./redux/actions/userActions";功能应用程序({用户:{已认证},clearUserData,getUserFromToken }){const [token, setToken] = useState(localStorage.IdToken);const [socket, setSocket] = useState(null);const 端点 = "http://localhost:3001";const setupSocket = () =>{如果(令牌&& !socket&&经过身份验证){const newSocket = io(ENDPOINT, {询问: {令牌,},});newSocket.on(断开连接", () => {设置套接字(空);setTimeout(setupSocket, 3000);});newSocket.on("connect", () => {console.log(成功,连接到套接字");});设置套接字(新套接字);}};useCallback(setupSocket(), [token]);useEffect(() => {如果(令牌){//解码令牌const decodedToken = jwtDecode(token);//令牌已过期if (decodedToken.exp * 1000 < Date.now()) {//从本地存储中删除令牌localStorage.removeItem(IdToken");设置令牌(空);清除用户数据();} 别的 {如果(!认证){设置身份验证();getUserFromToken(令牌);}如果(经过验证)返回;//获取用户}}}, [令牌, 已认证, clearUserData, getUserFromToken]);返回 (

<路由器><导航栏/><div className="容器"><开关><路由精确路径="/";组件={Home}/><路由精确路径=/login";组件={LoginContainer}/><路由精确路径="/signup";组件={注册}/><路由精确路径="/profile";组件={ProfileContainer}/><路由精确路径=/about";组件={关于容器}/><授权路由精确的path="/message/:username";组件={消息}已认证={已认证}/><授权路由精确的path="/posts/:postId";组件={PostDetailContainer}已认证={已认证}/></开关>

</路由器>

);}const mapStateToProps = (状态) =>({用户:state.user,});const mapDispatchToProps = {清除用户数据,设置身份验证,getUserFromToken,};导出默认连接(mapStateToProps, mapDispatchToProps)(App);

解决方案

使用 React.Strict 会让你的代码运行两次.查看此处了解更多相关信息.

Why does the useCallback hook execute twice? I got a warning advising me to use useCallback so I'm trying to do so. From my understanding useCallback will only execute whenever the object we pass to the array is updated. So my goal is for the websocket to connect once a token is loaded. It 'mostly' works; the socket is connected twice, the callback is running twice.

const setupSocket = () => {
    if (token && !socket && authenticated) {
      console.log(token, authenticated, socket === null);
      const newSocket = io(ENDPOINT, {
        query: {
          token,
        },
      });
      newSocket.on("disconnect", () => {
        setSocket(null);
        setTimeout(setupSocket, 3000);
      });
      newSocket.on("connect", () => {
        console.log("success, connected to socket");
      });
      setSocket(newSocket);
    }
  };

  useCallback(setupSocket(), [token]);

App.js

import React, { useEffect, useState, useCallback } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import "./App.css";
//Pages
import Home from "./pages/home.jsx";
import LoginContainer from "./pages/login/login.container";
import Signup from "./pages/signup";
import PostDetailContainer from "./pages/post-detail/post-detail.container.js";
import jwtDecode from "jwt-decode";
import ProfileContainer from "./pages/profile/profile.container";
import AboutContainer from "./pages/about/about.container";
//Components
import Navbar from "./components/Navbar";
import AuthRoute from "./utils/AuthRoute";
//Redux
import { connect } from "react-redux";
//SocketIO
import io from "socket.io-client";

//Actions
import {
  clearUserData,
  getUserFromToken,
  setAuthentication,
} from "./redux/actions/userActions";

function App({ user: { authenticated }, clearUserData, getUserFromToken }) {
  const [token, setToken] = useState(localStorage.IdToken);
  const [socket, setSocket] = useState(null);
  const ENDPOINT = "http://localhost:3001";

  const setupSocket = () => {
    if (token && !socket && authenticated) {
      const newSocket = io(ENDPOINT, {
        query: {
          token,
        },
      });
      newSocket.on("disconnect", () => {
        setSocket(null);
        setTimeout(setupSocket, 3000);
      });
      newSocket.on("connect", () => {
        console.log("success, connected to socket");
      });
      setSocket(newSocket);
    }
  };
  useCallback(setupSocket(), [token]);

  useEffect(() => {
    if (token) {
      //decode token
      const decodedToken = jwtDecode(token);
      //token is expired
      if (decodedToken.exp * 1000 < Date.now()) {
        //remove token from local storage
        localStorage.removeItem("IdToken");
        setToken(null);
        clearUserData();
      } else {
        if (!authenticated) {
          setAuthentication();
          getUserFromToken(token);
        }
        if (authenticated) return;
        //get user
      }
    }
  }, [token, authenticated, clearUserData, getUserFromToken]);

  return (
    <div className="App">
      <Router>
        <Navbar />
        <div className="container">
          <Switch>
            <Route exact path="/" component={Home} />
            <Route exact path="/login" component={LoginContainer} />
            <Route exact path="/signup" component={Signup} />
            <Route exact path="/profile" component={ProfileContainer} />
            <Route exact path="/about" component={AboutContainer} />
            <AuthRoute
              exact
              path="/message/:username"
              component={Message}
              authenticated={authenticated}
            />
            <AuthRoute
              exact
              path="/posts/:postId"
              component={PostDetailContainer}
              authenticated={authenticated}
            />
          </Switch>
        </div>
      </Router>
    </div>
  );
}
const mapStateToProps = (state) => ({
  user: state.user,
});

const mapDispatchToProps = {
  clearUserData,
  setAuthentication,
  getUserFromToken,
};
export default connect(mapStateToProps, mapDispatchToProps)(App);

解决方案

Using React.Strict will make your code run twice. Check out here for more information about this.

这篇关于useCallBack 执行两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆