useCallBack 执行两次

IT技术 javascript reactjs react-hooks
2021-04-29 03:09:47

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

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

应用程序.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);
2个回答

使用 React.Strict 会让你的代码运行两次。这里查看更多信息。

你的代码

useCallback(setupSocket(), [token]);

试试这个

useCallback(setupSocket, [token]);

如果那是一个错字,那么我希望你已经遇到了这个问题。如果没有并且您需要解释,那么就在这里。

假设你有这样的方法

function foo () {
  console.log('I am foo');
  return 'I am foo'; // Incase 'foo' is not void and returns something
};

方式 1:您正在执行 'foo' 并将返回值存储在 'refFoo' 中。

var refFoo = foo();

方式 2:您正在将 'foo' 的引用创建为“refFoo”。

var refFoo = foo;