admin管理员组文章数量:1356588
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 "./ponents/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="/" ponent={Home} />
<Route exact path="/login" ponent={LoginContainer} />
<Route exact path="/signup" ponent={Signup} />
<Route exact path="/profile" ponent={ProfileContainer} />
<Route exact path="/about" ponent={AboutContainer} />
<AuthRoute
exact
path="/message/:username"
ponent={Message}
authenticated={authenticated}
/>
<AuthRoute
exact
path="/posts/:postId"
ponent={PostDetailContainer}
authenticated={authenticated}
/>
</Switch>
</div>
</Router>
</div>
);
}
const mapStateToProps = (state) => ({
user: state.user,
});
const mapDispatchToProps = {
clearUserData,
setAuthentication,
getUserFromToken,
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
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 "./ponents/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="/" ponent={Home} />
<Route exact path="/login" ponent={LoginContainer} />
<Route exact path="/signup" ponent={Signup} />
<Route exact path="/profile" ponent={ProfileContainer} />
<Route exact path="/about" ponent={AboutContainer} />
<AuthRoute
exact
path="/message/:username"
ponent={Message}
authenticated={authenticated}
/>
<AuthRoute
exact
path="/posts/:postId"
ponent={PostDetailContainer}
authenticated={authenticated}
/>
</Switch>
</div>
</Router>
</div>
);
}
const mapStateToProps = (state) => ({
user: state.user,
});
const mapDispatchToProps = {
clearUserData,
setAuthentication,
getUserFromToken,
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
Share
Improve this question
edited Oct 7, 2020 at 16:15
Mint
asked Oct 7, 2020 at 3:08
MintMint
1,0592 gold badges19 silver badges33 bronze badges
3
- 1 If you are using React.Strict, it will run twice. Check here for details. React.Strict is usually used in index.tsx – Timmy Chan Commented Oct 7, 2020 at 3:31
- thank you! You should make this an answer so I can accept. – Mint Commented Oct 7, 2020 at 12:42
- Okay I have added an answer. – Timmy Chan Commented Oct 7, 2020 at 17:23
2 Answers
Reset to default 8Using React.Strict will make your code run twice. Check out here for more information about this.
Your code
useCallback(setupSocket(), [token]);
Try this
useCallback(setupSocket, [token]);
If that was a typo, then I hope you already got the issue. If not and you need explanation, then here it is.
Assume you have a methods like this
function foo () {
console.log('I am foo');
return 'I am foo'; // Incase 'foo' is not void and returns something
};
Way 1: You are executing 'foo' and storing return value in 'refFoo'.
var refFoo = foo();
Way 2: You are creating reference of 'foo' as "refFoo".
var refFoo = foo;
本文标签: javascriptuseCallBack executes twiceStack Overflow
版权声明:本文标题:javascript - useCallBack executes twice - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743966848a2570029.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论