Pippa97
Pippa97

Reputation: 99

React SetState array not updating

I have a Google map in my react application which allows users to sign up (by entering their name). It then gets their location every 1 second and sends it to all the other users currently using the app.

I am trying to plot the users on a map using google-map-react. This should update every time a user is added, or their location changes and reflect this with their marker moving on the map.

It is console logging the usersArray correctly, but users is not being updated, am I doing setState wrong?

const Map = ({ location, zoomLevel }) => {
    const { name } = useParams();
    const [messages, setMessages] = useState([]);
    const ws = useRef();
    let [latitude, setLatitude] = useState('');
    let [longitude, setLongitude] = useState('');
    const [isConnectionOpen, setConnectionOpen] = useState(false);
    const [users, setUsers] = useState([]);

    useEffect(() => {
        ws.current = new WebSocket('ws://localhost:8081');
        //new user has connected
        ws.current.onopen = () => {
            setConnectionOpen(true);
        };
        //sending message to other users
        ws.current.onmessage = (ev) => {
            const message = JSON.parse(ev.data);
            //update users function
            handleAddNewUser(message);
            setMessages((_messages) => [..._messages, message]);
        };
        return () => {};
    }, []);

    //checks if a message has been received my a new user. If existing user - update location
    function handleAddNewUser(message) {
        let usersArray = [];
        let newUser = true;
        if (users.length == 0) {
            usersArray.push(message);
        } else {
            for (let user of users) {
                if (message.sender == user.sender) {
                    newUser = false;
                    user = message;
                }
            }
            if (newUser == true) {
                usersArray.push(message);
            }
        }
        console.log(usersArray);
        // update the state to the updatedUsers
        setUsers(usersArray);
        console.log(users);
    } 

    //triggers the send function every 1 second
    useEffect(() => {
        const interval = setInterval(() => {
            send();
        }, 1000);
        return () => clearInterval(interval);
    }, []);

    //sends the users location as a message to all the other users
    const send = () => {
        if (navigator.geolocation) {
            navigator.geolocation.watchPosition(function (position) {
                latitude = position.coords.latitude.toString();
                longitude = position.coords.longitude.toString();
                ws.current.send(JSON.stringify({ sender: name, latitude: latitude, longitude: longitude }));
                setLatitude('');
                setLongitude('');
            });
        }
    };

    return (
        <div className='map'>
            <div className='google-map'>
                <GoogleMapReact
                    bootstrapURLKeys={{ key: 'keyID' }}
                    defaultCenter={location}
                    defaultZoom={zoomLevel}>
                     users.map(user => {
                    <MyGreatPlace lat={user.latitude} 
                    lng={user.longitude} text=  
                    {user.sender} />
                 })
                </GoogleMapReact>
            </div>
        </div>
    );
};
export default Map;

Also, when plotting the users on the map, i am getting this error: Unexpected token. Did you mean {'>'} or >?

Upvotes: 0

Views: 1070

Answers (2)

MWO
MWO

Reputation: 2806

Try logging users in useEffect with users in the dependency array. But you are having two useEffects in your component. You should only have one!

//triggers the send function every 1 second
useEffect(() => {
    console.log(users)
    const interval = setInterval(() => {
        send();
    }, 1000);
    return () => clearInterval(interval);
}, [users]);

And to map render users you usually do it like that (as an example):

<GoogleMapReact bootstrapURLKeys={{ key: 'keyID' }} defaultCenter={location} defaultZoom={zoomLevel}>
    {users?.map((user: any) => {
    return <MyGreatPlace lat={user.latitude} lng={user.longitude} text={user.sender} />
    })
    }
</GoogleMapReact>

Upvotes: 1

Paulliano
Paulliano

Reputation: 444

You should check if user exist first. Like this:

if(users){ setUsers(userArray) }

Upvotes: 2

Related Questions