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() } });