socket.io-客户端在 React Native 中多次发出事件
socket.io-client emmitting event multiple times in react native
我刚开始使用 socket.io 和 React native.I 我能够将 socket.io 实例与我的 node.js 后端连接,但是 socket.io 客户端是发射事件多个 times.The 应用程序变得非常复杂,所以我也试图解释我做了什么。
Main.js(用户从 App.js 重定向至此处)
我正在使用一个名为 react-native-tab-view 的库,我使用 useContext 来传递套接字instance.I已检查挂钩是否正常工作。
export const SocketObj = createContext()
const Main = ({ route }) => {
let [socket, setSocket] = useState(undefined)
const routesLength = useNavigationState(state => state.routes.length);
const connect = async () => {
if (routesLength == 1) {
setSocket(io("http://192.168.43.115:8000", {
transports: ['websocket'],
query: {
token: await AsyncStorage.getItem("token")
}
}))
} else {
const { socketInstanse } = route.params
setSocket(socketInstanse)
}
}
connect()
const layout = useWindowDimensions();
const [index, setIndex] = useState(0);
const [routes] = useState([
{ key: 'first', title: 'CHAT' },
{ key: 'second', title: 'PEOPLE' },
]);
const renderScene = SceneMap({
first: SplashScreen,
second: PeopleScreen,
});
return (
<SocketObj.Provider value={socket} >
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={(number) => {
setIndex(number)
}}
initialLayout={{ width: layout.width }}
/>
</SocketObj.Provider>
);
}
export default Main;
PeopleScreen.js
用户从 Main.js 被引导至此处。我在这里使用上下文 api 来获取套接字实例。
如您所见,我正在使用一个事件在连接时将“已连接”记录到控制台,但它发出多个 times.I 不想发出多个 times.Help 我
import { SocketObj } from "./Main"
const PeopleScreen = ({ route, navigation }) => {
let socket = useContext(SocketObj)
socket.on("connect", () => console.log("Connect"))
const [peopleList, setPeople] = useState([])
useEffect(
() => {
const fetchData = async () => {
try {
const response = await API.get('get/users', {
headers: {
'Content-Type': 'application/json',
"auth-token": await AsyncStorage.getItem("token")
}
})
setPeople(response.data)
} catch (err) {
console.log(err.response)
}
}
fetchData()
}, []
)
return (
<View style={{
flex: 1,
backgroundColor: '#fff',
width: '100%',
height: '100%'
}} >
<View>
{
peopleList.map(
(i, key) => {
return (
<View style={{
display: 'flex',
flexDirection: 'row',
top: 40,
marginVertical: 5,
marginBottom: 10,
backgroundColor: 'grey',
height: 50
}}
key={key} >
<Text style={{
maxWidth: "50%"
}} >{i.firstName + ' ' + i.email}</Text>
<TouchableOpacity
onPress={
async () => {
console.log(socket)
API.post('post/add-friend', {
friend_email: i.email
}, {
headers: {
"auth-token": await AsyncStorage.getItem("token")
}
}).then(
data => console.log(data.data)
)
}
}
style={{
backgroundColor: 'rgb(255, 105, 105)',
width: 130,
justifyContent: 'center',
alignItems: 'center',
left: 150
}}
activeOpacity={0.6} >
<Text style={{
color: 'white',
}} >Add Friend</Text>
</TouchableOpacity>
</View>
)
}
)
}
</View>
</View >
)
}
export default PeopleScreen
我忽略了不必要的导入。
尝试把你的 connect()
放在一个 useEffect
中,用一个空数组作为 useEffect
的第二个参数,然后你的 connect
函数将只在第一个被调用Main.js.
的渲染
...
const connect = async () => {
if (routesLength == 1) {
setSocket(io("http://192.168.43.115:8000", {
transports: ['websocket'],
query: {
token: await AsyncStorage.getItem("token")
}
}))
} else {
const { socketInstanse } = route.params
setSocket(socketInstanse)
}
}
useEffect(() => {
connect();
}, []);
...
if (!socket) return null; // or you can return a loading page
return (
<SocketObj.Provider value={socket} >
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={(number) => {
setIndex(number)
}}
initialLayout={{ width: layout.width }}
/>
</SocketObj.Provider>
);
这是由于在 Main.js 中初始化套接字多个 time.Put 实例而发生的。
如果套接字实例为空,则初始化套接字。
{ useEffect(() => { if(!isConnected){ connect() } });
我刚开始使用 socket.io 和 React native.I 我能够将 socket.io 实例与我的 node.js 后端连接,但是 socket.io 客户端是发射事件多个 times.The 应用程序变得非常复杂,所以我也试图解释我做了什么。
Main.js(用户从 App.js 重定向至此处)
我正在使用一个名为 react-native-tab-view 的库,我使用 useContext 来传递套接字instance.I已检查挂钩是否正常工作。
export const SocketObj = createContext()
const Main = ({ route }) => {
let [socket, setSocket] = useState(undefined)
const routesLength = useNavigationState(state => state.routes.length);
const connect = async () => {
if (routesLength == 1) {
setSocket(io("http://192.168.43.115:8000", {
transports: ['websocket'],
query: {
token: await AsyncStorage.getItem("token")
}
}))
} else {
const { socketInstanse } = route.params
setSocket(socketInstanse)
}
}
connect()
const layout = useWindowDimensions();
const [index, setIndex] = useState(0);
const [routes] = useState([
{ key: 'first', title: 'CHAT' },
{ key: 'second', title: 'PEOPLE' },
]);
const renderScene = SceneMap({
first: SplashScreen,
second: PeopleScreen,
});
return (
<SocketObj.Provider value={socket} >
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={(number) => {
setIndex(number)
}}
initialLayout={{ width: layout.width }}
/>
</SocketObj.Provider>
);
}
export default Main;
PeopleScreen.js
用户从 Main.js 被引导至此处。我在这里使用上下文 api 来获取套接字实例。 如您所见,我正在使用一个事件在连接时将“已连接”记录到控制台,但它发出多个 times.I 不想发出多个 times.Help 我
import { SocketObj } from "./Main"
const PeopleScreen = ({ route, navigation }) => {
let socket = useContext(SocketObj)
socket.on("connect", () => console.log("Connect"))
const [peopleList, setPeople] = useState([])
useEffect(
() => {
const fetchData = async () => {
try {
const response = await API.get('get/users', {
headers: {
'Content-Type': 'application/json',
"auth-token": await AsyncStorage.getItem("token")
}
})
setPeople(response.data)
} catch (err) {
console.log(err.response)
}
}
fetchData()
}, []
)
return (
<View style={{
flex: 1,
backgroundColor: '#fff',
width: '100%',
height: '100%'
}} >
<View>
{
peopleList.map(
(i, key) => {
return (
<View style={{
display: 'flex',
flexDirection: 'row',
top: 40,
marginVertical: 5,
marginBottom: 10,
backgroundColor: 'grey',
height: 50
}}
key={key} >
<Text style={{
maxWidth: "50%"
}} >{i.firstName + ' ' + i.email}</Text>
<TouchableOpacity
onPress={
async () => {
console.log(socket)
API.post('post/add-friend', {
friend_email: i.email
}, {
headers: {
"auth-token": await AsyncStorage.getItem("token")
}
}).then(
data => console.log(data.data)
)
}
}
style={{
backgroundColor: 'rgb(255, 105, 105)',
width: 130,
justifyContent: 'center',
alignItems: 'center',
left: 150
}}
activeOpacity={0.6} >
<Text style={{
color: 'white',
}} >Add Friend</Text>
</TouchableOpacity>
</View>
)
}
)
}
</View>
</View >
)
}
export default PeopleScreen
我忽略了不必要的导入。
尝试把你的 connect()
放在一个 useEffect
中,用一个空数组作为 useEffect
的第二个参数,然后你的 connect
函数将只在第一个被调用Main.js.
...
const connect = async () => {
if (routesLength == 1) {
setSocket(io("http://192.168.43.115:8000", {
transports: ['websocket'],
query: {
token: await AsyncStorage.getItem("token")
}
}))
} else {
const { socketInstanse } = route.params
setSocket(socketInstanse)
}
}
useEffect(() => {
connect();
}, []);
...
if (!socket) return null; // or you can return a loading page
return (
<SocketObj.Provider value={socket} >
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={(number) => {
setIndex(number)
}}
initialLayout={{ width: layout.width }}
/>
</SocketObj.Provider>
);
这是由于在 Main.js 中初始化套接字多个 time.Put 实例而发生的。 如果套接字实例为空,则初始化套接字。
{ useEffect(() => { if(!isConnected){ connect() } });