I am implementing mapbox which is called from the parent when I go to create a post. Although the coordinates are passed from the parent container to the child (which has the map) requesting the location of the user, the map renders fine changing location but the problem appears when I start writing in the parent inputs. The useffect that contains the map is always called by re-rendering the map for each character.
MapComponent
import React, { useEffect, useRef, useState } from 'react';
// Map-box
import mapboxgl from 'mapbox-gl';
// Style
import './style.sass';
// Map-box-access token
mapboxgl.accessToken = process.env.REACT_APP_MAP_BOX_TOKEN;
const MapComponent = ({currentPosition}) => {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(-70.9);
const [lat, setLat] = useState(42.35);
const [zoom, setZoom] = useState(11);
useEffect(() => {
console.log('typing')
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/streets-v11',
center: [lng, lat],
zoom: zoom
});
setLng(currentPosition.longitude);
setLat(currentPosition.latitude);
})
return(
<div>
<div ref={mapContainer} className="map-container" />
</div>
)
}
export default MapComponent;
Post Component
const CreatePost = () => {
const [post, setPost] = useState({});
const [images, setImages] = useState([]);
const [currentPosition, setCurrentPosition] = useState({
latitude: 37.419857,
longitude: -122.078827,
zoom: 11
})
useEffect(() => {
navigator.geolocation.getCurrentPosition(getPosition)
},[]);
const getPosition = (position) => {
const {
latitude,
longitude
} = position.coords;
setCurrentPosition({latitude: latitude, longitude: longitude});
}
const navigate = useNavigate();
const notifySuccess = () => toast("Post created successfully");
const notifyError = ({message}) => toast(message);
const handlerPost = (e) => {
e.preventDefault();
const { name, value } = e.target;
const postData = {[name]: value};
const newPost = {...post, ...postData};
setPost(newPost);
}
const convertToBase64 = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
};
const selectImages = async(e) => {
const { files } = e.target;
if(!files || files.length === 0) {
throw new Error('You must select a file to upload');
}
const filesArray = files;
let filesPath = [];
for(let i = 0; i < filesArray.length; i++) {
const base64 = await convertToBase64(filesArray[i])
filesPath.push(base64);
}
setImages(JSON.stringify(filesPath));
}
const createPost = async() => {
const user = supabase.auth.user();
post['user_id'] = user.id;
post['user_email'] = user.email;
post['images'] = images;
try {
const { data, error } = await supabase
.from('posts')
.insert([post]);
if(error) throw error;
notifySuccess();
setTimeout(() => {
navigate('/');
}, 4000);
} catch (error) {
notifyError(error)
}
}
return(
<Flex
minH={'100vh'}
align="top"
pt={'100px'}
justify="center"
bg={useColorModeValue('gray.50', 'gray.800')}
>
<Stack spacing={8} align={"center"}>
<Stack>
<Heading
color={useColorModeValue('black', 'white')}
fontSize={'4xl'}
>
Create your post
</Heading>
</Stack>
<Box
rounded={'lg'}
bg={useColorModeValue('white', 'gray.700')}
boxShadow={'lg'}
p={8}
>
<Stack spacing={4}>
<FormControl>
<Input
type="file"
accept="image/*"
multiple={true}
onChange={(e) => selectImages(e)}
/>
</FormControl>
<FormControl>
<FormLabel>Title</FormLabel>
<Input name="title" value={post.title || ''} onChange={(e) => handlerPost(e)}></Input>
</FormControl>
<FormControl>
<FormLabel>Description</FormLabel>
<Textarea
value={post.content || ''}
onChange={(e) => handlerPost(e)}
name="content"
placeholder='Here is a sample placeholder'
size='sm'
/>
</FormControl>
{console.log('current before', currentPosition)}
<Box h="150" w="100%">
<MapComponent currentPosition={currentPosition}/>
</Box>
<Stack>
<Button
bg={'green.400'}
color={'white'}
onClick={() => createPost()}
_hover={{
bg: 'green.500'
}}
>Create Post</Button>
</Stack>
</Stack>
</Box>
</Stack>
<ToastContainer
position="bottom-center"
autoClose={2000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
/>
</Flex>
)
}
export default CreatePost;
Every time I enter a character, the "typing" of the useEffect appears