useCallBack 执行两次

Min*_*int 3 javascript reactjs react-hooks

为什么 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]);
Run Code Online (Sandbox Code Playgroud)

应用程序.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);
Run Code Online (Sandbox Code Playgroud)

Tim*_*han 8

使用 React.Strict 会让你的代码运行两次。请查看此处以获取有关此内容的更多信息。