Mapbox re render when typing on inputs

Viewed 15

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

0 Answers
Related