简体   繁体   中英

Getting Uncaught RangeError: Maximum call stack size exceeded in React

I'm a beginner with React and I have been coding a project for one of the courses in uni. However, I have been now struggling for quite some time with following error: Uncaught RangeError: Maximum call stack size exceeded. I have tried to find a solution with no luck.

Here is my code for the React component that causes the error:

`

import { Container } from "react-bootstrap"
import { useParams } from "react-router"
import apiService from "../services/apiService"
import { useEffect, useState } from "react"
import Spinner from 'react-bootstrap/Spinner';

const GOOGLE_API_KEY = process.env.REACT_APP_GOOGLE_API_KEY

export const TreeProfile = (props) => {
  const [tree, setTree] = useState({})
  const [fetching, setFetching] = useState(true)
  const [zoom, setZoom] = useState("12")
  const [location, setLocation] = useState({latitude: "", longitude: ""})

  let { id } = useParams()

  const handleZoomChange2 = (event) => {
    console.log(event.target.value)
    setZoom(event.target.value)
  }

  console.log("Called TreeProfile")

  useEffect(() => {
    console.log("id", id)
    apiService.getOne(id).then(t => {
      console.log("data", t)
      setTree(t)
      setLocation({latitude: t.location.latitude, longitude: t.location.longitude})
      setFetching(false)
    })
  }, [])

  return (
    <Container className="treeprofile-page">
      {
        fetching === false ?
        <img style={{height: '200px', width: '300px'}} src={`data:image/${tree.image.contentType};base64,${btoa(String.fromCharCode(...new Uint8Array(tree.image.data.data)))}`} alt='' />
        :
        <Spinner animation="border" variant="primary" />
      }
      
      <h1>{tree.name}</h1>
      {
        fetching === false ?
        <h3>Planted on {new Date(tree.createdAt).toDateString()}</h3>
        :
        null
      }
      <h3>Planted by {tree.user}</h3>

      {
        fetching === false ?
        <div>
        <img src={`https://maps.googleapis.com/maps/api/staticmap?center=${location.latitude},${location.longitude}&format=gif&zoom=${zoom}&size=300x200&markers=color:red%7C${location.latitude},${location.longitude}&key=${GOOGLE_API_KEY}`} alt='' />
        </div>
        :
        null
      }
      <div>
        <input className="m-3" type="range" min="1" max="16" value={zoom} onChange={handleZoomChange2} />
      </div>

      <button type="button" className="btn btn-primary" >Add update</button>
      
    </Container>
  )
}

`

The error happens every time I try to update the zoom level by sliding the slider, which calls handleZoomChange2 function that sets the state. I have other component in different route with the same functionality and it works fine. However, this one for some reason causes the error constantly.

The apiService fetches the data with axios from the backend, which in turn fetches the data from MongoDB.

I tried to update zoom level by sliding the slider input, which calls on handleZoomChange2 setting a new state to the zoom. However, the code throws an error Maximum call stack size exceeded. Please, help!

Error:

TreeProfile.js:38 Uncaught RangeError: Maximum call stack size exceeded
at TreeProfile (TreeProfile.js:38:1)
at renderWithHooks (react-dom.development.js:16305:1)
at updateFunctionComponent (react-dom.development.js:19588:1)
at beginWork (react-dom.development.js:21601:1)
at beginWork$1 (react-dom.development.js:27426:1)
at performUnitOfWork (react-dom.development.js:26557:1)
at workLoopSync (react-dom.development.js:26466:1)
at renderRootSync (react-dom.development.js:26434:1)
at recoverFromConcurrentError (react-dom.development.js:25850:1)
at performSyncWorkOnRoot (react-dom.development.js:26096:1)

In case somebody stumbles upon this, here's the solution:

Cause of the problem

Encoding of the image from array buffer tree.image.data.data to base64 was causing the error of Uncaught RangeError: Maximum call stack size exceeded . I'm not quite certain why exactly, somebody smarted than me may explain it.

<img style={{height: '200px', width: '300px'}} src={`data:image/${tree.image.contentType};base64,${btoa(String.fromCharCode(...new Uint8Array(tree.image.data.data)))}`} alt='' />

Solution

I found the solution to this problem from this Stackoverflow thread . There they discuss the problem more in detail, however, here is the solution that worked for me.

  const _arrayBufferToBase64 = ( buffer ) => {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
  }

here the buffer is tree.image.data.data (the array buffer of unit8array) and the function returns base64 encoded result. My code after these changes looks following

import { Container } from "react-bootstrap"
import { useParams } from "react-router"
import apiService from "../services/apiService"
import { useEffect, useState } from "react"
import Spinner from 'react-bootstrap/Spinner';

const GOOGLE_API_KEY = process.env.REACT_APP_GOOGLE_API_KEY

export const TreeProfile = (props) => {
  const [tree, setTree] = useState(null)
  const [fetching, setFetching] = useState(true)
  const [zoom, setZoom] = useState("12")
  const [location, setLocation] = useState({latitude: "", longitude: ""})

  let { id } = useParams()

  console.log("Called TreeProfile")
  console.log("fetching", fetching)

  useEffect(() => {
    console.log("id", id)
    apiService.getOne(id).then(t => {
      console.log("data", t)
      setTree(t)
      setLocation({latitude: t.location.latitude, longitude: t.location.longitude})
      setFetching(false)
    })
  }, [])
  
  const handleZoomChange2 = (event) => {
    console.log(event.target.value)
    setZoom(event.target.value)
  }
  const test = (event) => {
    console.log(event.target.value)
    setFetching(!fetching)
  }

  const _arrayBufferToBase64 = ( buffer ) => {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
  }


  if (tree) {
    return (
      <Container className="treeprofile-page">
        <div>
          <img style={{height: '200px', width: '300px'}} src={`data:image/${tree.image.contentType};base64,${_arrayBufferToBase64(tree.image.data.data)}`} alt='' />
          <h1>{tree.name}</h1>
          <h3>Planted on {new Date(tree.createdAt).toDateString()}</h3>
          <h3>Planted by {tree.user}</h3>
          </div>
        <img src={`https://maps.googleapis.com/maps/api/staticmap?center=${location.latitude},${location.longitude}&format=gif&zoom=${zoom}&size=300x200&markers=color:red%7C${location.latitude},${location.longitude}&key=${GOOGLE_API_KEY}`} alt='' />
        <div>
          <input className="m-3" type="range" min="1" max="16" value={zoom} onChange={handleZoomChange2} />
        </div>
  
        <button type="button" className="btn btn-primary" onClick={test} >Add update</button>
        
      </Container>
    )
  } else {
    return (
      <Container>
        <Spinner animation="border" variant="primary" />
      </Container>
    )
  }
  
}

Hope this helps anybody facing the same problems!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM