SAYAN
SAYAN

Reputation: 35

socket.io-client emmitting event multiple times in react native

I am new to using socket.io with react native.I am able to connect the socket.io instance with my node.js backend but the socket.io client is emmitting events multiple times.The app has grown quite complex so,I am also trying to explain what I did.

Main.js (User is redirected here from App.js)

I am using a library called react-native-tab-view and I used useContext to pass the socket instance.I have checked that the hook is working properly.

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

The user is directed here from Main.js. I have used the context api here to get the socket instance. As you can see , i am using an event to log "Connected" to the console when connected but it is emitting multiple times.I don't want to emit it multiple times.Help me

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

I have ignored unnecessary imports.

Upvotes: 0

Views: 1708

Answers (2)

Antier Solutions
Antier Solutions

Reputation: 1392

It happens due to initialisation of socket multiple time.Put instance in Main.js . If socket instance is empty then initialise socket.

  { useEffect(() => { if(!isConnected){ connect() } }); 

Upvotes: 1

Thiago Nelsi do Couto
Thiago Nelsi do Couto

Reputation: 96

Try to put your connect() inside an useEffect with an empty array as second argument of useEffect, then your connect function will be called only at the first render of 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>
  );


Upvotes: 1

Related Questions