如何修复超出最大调用堆栈大小

2024-05-21

有一个 MERN + Firebase 应用程序并收到此错误和一堆 atdeepExtend (deepCopy.ts:71)

RangeError: Maximum call stack size exceeded
getApps [as apps]
src/firebaseNamespaceCore.ts:172
  169 |  */
  170 | function getApps(): FirebaseApp[] {
  171 |   // Make a copy so caller cannot mutate the apps list.
> 172 |   return Object.keys(apps).map(name => apps[name]);
      | ^  173 | }
  174 | 
  175 | function registerComponent(

这是导致问题的 JS 文件。我想不通。

import React, { useState, useEffect, useRef } from 'react';
import { Link } from 'react-router-dom';
import { Row, Col, Image, ListGroup, Card, Button } from 'react-bootstrap';
import Rating from '../components/Rating';
import socketIOClient from 'socket.io-client';
import axios from 'axios';
// import Product from '../components/Product';
import dotenv from 'dotenv';
import { ReactMediaRecorder } from 'react-media-recorder';
import firebase from 'firebase';
import 'firebase/firestore';
import firebaseKeys from 'firebase';
const ENDPOINT = 'http://localhost:5000';

dotenv.config();
firebase.initializeApp(firebaseKeys);
firebase.analytics();
export const storage = firebase.storage();

const AudioPreview = ({ stream }) => {
  const audioRef = useRef(null);

  useEffect(() => {
    if (stream) audioRef.current.srcObject = stream;
  }, [stream]);

  if (!stream) return null;
  return <audio ref={audioRef} autoPlay controls />;
};

const VideoPreview = ({ stream }) => {
  const videoRef = useRef(null);

  useEffect(() => {
    if (stream) videoRef.current.srcObject = stream;
  }, [stream]);

  if (!stream) return null;
  return <video ref={videoRef} autoPlay controls />;
};

function Controls({ status, startRecording, stopRecording, mediaBlobUrl }) {
  const [url, setURL] = useState('');
  async function uploadFile() {
    const blob = await fetch(mediaBlobUrl).then((r) => r.blob());
    const path = '/recordings/one';
    firebase
      .storage()
      .ref(path)
      .put(blob)
      .then(function (snapshot) {
        console.log('Uploaded complete');
      });

    storage.ref(path).getDownloadURL().then(setURL);
  }
  return (
    <Row>
      <span className='uk-text-meta'>{status}</span>
      <button className='uk-margin-small-left' type='button' onClick={startRecording} disabled={status === 'recording'}>
        Start
      </button>
      <button className='uk-margin-small-left' type='button' onClick={stopRecording} disabled={status === 'stopped'}>
        Stop
      </button>
      <button className='uk-margin-small-left' type='button' onClick={uploadFile} disabled={status !== 'stopped'}>
        upload
      </button>
      {url && (
        <a className='uk-margin-small-left' href={url} target='_blank' rel='noopener noreferrer'>
          open
        </a>
      )}
    </Row>
  );
}

function RecordAudio() {
  return (
    <ReactMediaRecorder
      audio
      render={({ status, startRecording, stopRecording, previewStream, mediaBlobUrl }) => (
        <div>
          {status === 'recording' ? (
            <AudioPreview stream={previewStream} />
          ) : (
            <audio src={mediaBlobUrl} controls autoPlay />
          )}
          <Controls
            status={status}
            startRecording={startRecording}
            stopRecording={stopRecording}
            mediaBlobUrl={mediaBlobUrl}
          />
        </div>
      )}
    />
  );
}

function RecordVideo() {
  return (
    <ReactMediaRecorder
      video
      render={({ status, startRecording, stopRecording, previewStream, mediaBlobUrl }) => (
        <div>
          {status === 'recording' ? (
            <VideoPreview stream={previewStream} />
          ) : (
            <video src={mediaBlobUrl} controls autoPlay />
          )}
          <Controls
            status={status}
            startRecording={startRecording}
            stopRecording={stopRecording}
            mediaBlobUrl={mediaBlobUrl}
          />
        </div>
      )}
    />
  );
}

// function RecordScreen() {
//   return (
//     <ReactMediaRecorder
//       screen
//       render={({ status, startRecording, stopRecording, mediaBlobUrl }) => (
//         <div>
//           <video src={mediaBlobUrl} controls autoPlay />
//           <Controls
//             status={status}
//             startRecording={startRecording}
//             stopRecording={stopRecording}
//             mediaBlobUrl={mediaBlobUrl}
//           />
//         </div>
//       )}
//     />
//   );
// }

function handleClick(num) {
  this.setState(num);
}

const ProductScreen = ({ match }) => {
  const [product, setProduct] = useState({});
  //const [state, setState] = useState(0);
  this.setState(0);

  useEffect(() => {
    console.log('about to fetch product');
    const fetchProduct = async () => {
      console.log('Below is the id param waht the fuck is it?');
      console.log(match.params.id);
      const { data } = await axios.get(`http://localhost:5000/api/products/${match.params.id}`);

      setProduct(data);
    };
    fetchProduct();
    const socket = socketIOClient(ENDPOINT);
    socket.on('status-update', function (call) {
      const stext = document.getElementById('statusText');
      stext.innerText = call;
    });
    // CLEAN UP THE EFFECT
    // return () => socket.disconnect();
  }, [match]);

  return (
    <>
      <Link className='btn btn-light my-3' to='/'>
        Go Back
      </Link>
      <Row>
        <Col md={6}>
          <Image src={product.image} alt={product.name} fluid />
        </Col>
        <Col md={3}>
          <ListGroup variant='flush'>
            <ListGroup.Item>
              <h3>{product.name}</h3>
            </ListGroup.Item>
            <ListGroup.Item>
              <Rating value={product.rating} text={`${product.numReviews} reviews`} />
            </ListGroup.Item>
            <ListGroup.Item>Price : {product.price}</ListGroup.Item>
            <ListGroup.Item>Description : {product.description}</ListGroup.Item>
          </ListGroup>
        </Col>
        <Col md={3}>
          <Card>
            <ListGroup variant='flush'>
              <ListGroup.Item>
                <Row>
                  <Col>Price: </Col>
                  <Col>
                    <strong>${product.price}</strong>
                  </Col>
                </Row>
              </ListGroup.Item>
            </ListGroup>
            <ListGroup variant='flush'>
              <ListGroup.Item>
                <Row>
                  <Col>Status: </Col>
                  <Col>{product.countInStock > 0 ? 'In Stock' : 'Out of Stock'}</Col>
                </Row>
              </ListGroup.Item>
              <ListGroup.Item>
                <Button
                  //   onClick={addToCartHandler}
                  className='btn-block w-100'
                  type='button'
                  disabled={product.countInStock === 0}
                >
                  Add To Cart
                </Button>
              </ListGroup.Item>
              <ListGroup.Item>
                <Row>
                  <Col>Copy Status: </Col>
                  <Col>
                    <h2 id='statusText'>Share</h2>
                    <button type='button' onClick={() => handleClick(1)}>
                      audio
                    </button>
                    <button type='button' onClick={() => handleClick(2)}>
                      video
                    </button>
                    {/* <button type="button" onClick={() => handleClick(3)}>
        screen
      </button> */}
                    {state === 1 && <RecordAudio />}
                    {state === 2 && <RecordVideo />}
                    {/* {state === 3 && <RecordScreen />} */}
                  </Col>
                </Row>
              </ListGroup.Item>
            </ListGroup>
          </Card>
        </Col>
      </Row>
    </>
  );
};

export default ProductScreen;

另外,获取 Core Firebase JS SDK 必须总是......错误?

我的index.html中有这个

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta name="description" content="Web site created using create-react-app" />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
      referrerpolicy="no-referrer"
    />
    <title>Welcom To BShop</title>
  </head>
  <body>
    The core Firebase JS SDK is always required and must be listed first
    <script src="https://www.gstatic.com/firebasejs/8.7.1/firebase-app.js"></script>

    <!-- TODO: Add SDKs for Firebase products that you want to use
     https://firebase.google.com/docs/web/setup#available-libraries -->
    <script src="https://www.gstatic.com/firebasejs/8.7.1/firebase-analytics.js"></script>

    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

更新(firebase 问题或一次又一次重新加载 firebase?)

如果我注释掉这 3 行以及任何对Storage

然后错误就消失了。

// firebase.initializeApp(firebaseKeys);
// firebase.analytics();
// export const storage = firebase.storage();

这不是分析线!


好的,我在上面留下了我的评论,然后决定看看你在哪里打电话setState- 并且您直接在组件渲染中执行此操作。这是有问题的代码:

const ProductScreen = ({ match }) => {
  const [product, setProduct] = useState({});
  const [state, setState] = useState(0);
  this.setState(0); // <- This is bad
  ...
}

每次您的 ProductScreen 呈现时,您都在调用setState, 什么导致ProductScreen再次渲染,然后调用setState再次,这导致ProductScreen再次渲染,然后调用setState再次,这导致ProductScreen再次渲染,然后调用setState再次,这导致ProductScreen再次渲染,然后调用setState再次,这导致ProductScreen再次渲染,然后调用setState再次,这导致ProductScreen再次渲染,然后调用setState再次,这导致ProductScreen再次渲染,然后调用setState again.


你明白了。你应该只打电话setState当发生某些事情时 - 例如在单击处理程序中或useEffect hook.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何修复超出最大调用堆栈大小 的相关文章

随机推荐