Контактная форма responsejs с функциями nodemailer и firebase — RangeError: превышен максимальный размер стека вызовов

Я думаю, что я на последнем этапе создания формы обратной связи, но я не могу ее получить. У меня есть другая форма, настроенная аналогично, хотя она не имеет отношения к функциям firebase в ней. Я просмотрел пару руководств, чтобы увидеть, как я могу это исправить, но не повезло.

Для любопытных, это те, на которые я смотрел:

  1. https://pantaley.com/blog/How-to-integrate-Serverless-contact-form-using-Firebase-Cloud-functions-in-React/

  2. https://betterprogramming.pub/a-simple-and-easy-contact-form-step-by-step-tutorial-react-js-1532bc025980

  3. https://academind.com/tutorials/sending-an-email-with-react-and-cloud-functions/ ‹- мой любимый

У меня есть код, настроенный в моих функциях firebase index.js, и я протестировал его с помощью почтальона, и он прошел успешно. поэтому я знаю, что код index.js работает.

но когда я пытаюсь создать страницу для связи с приведенным ниже кодом, помеченным как исходный код, и нажимаю созданную мной кнопку отправки, ничего не происходит, и я вижу эту ошибку в консоли при проверке.

RangeError: Maximum call stack size exceeded
    at FiberNode.hasOwnProperty (<anonymous>)
    at mapValues (serializer.ts:29)
    at Serializer.encode (serializer.ts:61)
    at serializer.ts:61
    at mapValues (serializer.ts:30)
    at Serializer.encode (serializer.ts:61)
    at serializer.ts:61
<error repeats>

вот мой код для моей контактной формы. Когда я перехожу, он вешает трубку

sendEmail({
   name: nameRef,
   email: emailRef,
   message: messageRef
})

Исходный код contactUs.js

import React, {useRef, useState} from "react";
import {useAuth} from "../contexts/AuthContext";
import {useHistory} from "react-router-dom";
import firebase from 'firebase/app';
import classes from "./xclasses.module.scss";
import {Button, Container, Form} from "react-bootstrap";

const sendEmail = firebase.functions().httpsCallable('sendEmail');

export default function ContactUs() {
    const nameRef = useRef();
    const emailRef = useRef();
    const messageRef = useRef();
    const firmRef = useRef();
    const history = useHistory();

    const [error, setError] = useState("")
    const [loading, setLoading] = useState(false)

Что я пробовал:

Я попытался переместить вызов sendEmail за пределы handleSubmit самостоятельно из-за этого SO Post говорит, что не следует вызывать вызов setState внутри вызова рендеринга в основном потому, что он выполняет бесконечный цикл.

См. также:  Поиск последней грамматики GCC GIMPLE

Форма очищается после нажатия кнопки отправки из-за вызова history.push (/ ContactUs), но электронное письмо не отправляется, и я не вижу вызова sendMail на моей панели функций firebase.

Попробуйте B-код

    const submitForm = async () => {
        await sendEmail({
            name: nameRef,
            email: emailRef,
            message: messageRef
        }).then(result => {
            console.log("contact-us message sent with " + result.data.message)        
        })
            .catch(error => {
                console.log(error);               
            });
    }*/

Исходный код

    async function handleSubmit(e) {
        e.preventDefault()

        setError("")
        setLoading(true)

       sendEmail({
            name: nameRef,
            email: emailRef,
            message: messageRef
        }).then(result => {
            console.log("contact-us message sent with " + result.data.message)            
        })
            .catch(error => {
                console.log(error);                
            });

        history.push("/ContactUs")
        setLoading(false)
    }

    return (
        <React.Fragment>
            <div className={classes.body}>
                <Container>
                    <div className={classes.body}>
                        <h2>Contact Us</h2>
                        {/*<Form onSubmit={submitForm}>*/} // also tried this (Try B Code)
                        <Form onSubmit={handleSubmit}>
                            <Form.Group id="email">
                                <Form.Label>Email</Form.Label>
                                <Form.Control type="email" ref={emailRef} required/>
                            </Form.Group>
                            <Form.Group id="name">
                                <Form.Label>Name</Form.Label>
                                <Form.Control type="text" ref={nameRef} required/>
                            </Form.Group>
                            <Form.Group id="message">
                                <Form.Label>Message</Form.Label>
                                <Form.Control type="text" ref={messageRef} required/>
                            </Form.Group>

                            <Form.Group id="firm">
                                <Form.Label>Firm</Form.Label>
                                <Form.Control type="text" ref={firmRef} required/>
                            </Form.Group>

                            {/*<Button onClick={submitForm} className="w-100" type="submit">*/}
                            // also tried this ^^ (Try B Code)
                            <Button disabled={loading} className="w-100" type="submit">
                                Send
                            </Button>
                        </Form>
                    </div>
                </Container>
            </div>
        </React.Fragment>
    )
}

Любая помощь приветствуется.

Обновление от 2021/05/16 из @somoneСпециальные комментарии

Обновленный код:

import React, {useRef, useState} from "react";
import {useAuth} from "../contexts/AuthContext";
import {useHistory} from "react-router-dom";
import firebase from 'firebase/app';
import classes from "./SyncManagerDemo.module.scss";
import {Button, Container, Form} from "react-bootstrap";


export default function ContactUs() {
    const nameRef = useRef();
    const emailRef = useRef();
    const messageRef = useRef();
    const firmRef = useRef();
    const history = useHistory();

    const [error, setError] = useState("")
    const [loading, setLoading] = useState(false)


    async function handleSubmit(e) {
        e.preventDefault()

        const sendEmail = firebase.functions().httpsCallable('sendEmail');
        console.log("nameRef: " + nameRef.current.value);
        console.log("emailRef: " + emailRef.current.value);
        console.log("messageRef: " + messageRef.current.value);

        const test = await sendEmail({
            name: nameRef.current.value,
            email: emailRef.current.value,
            message: messageRef.current.value
        }).then(function (result) {
            var messageSent = result.data.message;
            console.log(nameRef.current + " " + emailRef.current + " " + messageRef.current + " " + messageSent)
        });        
    }
return (
        <React.Fragment>
            <div className={classes.body}>
                <Container>
                    <div className={classes.body}>
                        <h2>Contact Us</h2>
                        {/*todo: convert to Bootstrap inputs: https://getbootstrap.com/docs/4.0/components/forms/ */}
                        {/*<Form onSubmit={submitForm}>*/}
                        {/*<Form onSubmit={sendEmail}>*/}
                        {/*<Form onSubmit={sendEmail2}>*/}
                        <Form onSubmit={handleSubmit}>
                            <Form.Group id="email">
                                <Form.Label>Email</Form.Label>
                                <Form.Control type="email" ref={emailRef} required/>
                            </Form.Group>
                            <Form.Group id="name">
                                <Form.Label>Name</Form.Label>
                                <Form.Control type="text" ref={nameRef} required/>
                            </Form.Group>
                            <Form.Group id="message">
                                <Form.Label>Message</Form.Label>
                                <Form.Control type="text" ref={messageRef} required/>
                            </Form.Group>

                            <Form.Group id="firm">
                                <Form.Label>Firm</Form.Label>
                                <Form.Control type="text" ref={firmRef} required/>
                            </Form.Group>

                            {/*<Button onClick={submitForm} className="w-100" type="submit">*/}
                            <Button disabled={loading} className="w-100" type="submit">
                                Send
                            </Button>
                        </Form>
                    </div>
                </Container>
            </div>
        </React.Fragment>
    )
}

теперь я получаю ошибку:

Uncaught (in promise) Error: internal
HttpsErrorImpl                          error.ts:65
_errorForResponse                       error.ts:175
(anonymous function)                    service.ts:276
step                                    tslib.es6.js:100
(anonymous function)                    tslib.es6.js:81
fulfilled                               tslib.es6.js:71
Async call from async function
handleSubmit                            ContactUs.js:47
callCallback                            react-dom.development.js:3945
invokeGuardedCallbackDev                react-dom.development.js:3994
invokeGuardedCallback                   react-dom.development.js:4056
invokeGuardedCallbackAndCatchFirstError react-dom.development.js:4070
executeDispatch                         react-dom.development.js:8243
processDispatchQueueItemsInOrder        react-dom.development.js:8275
processDispatchQueue                    react-dom.development.js:8288
dispatchEventsForPlugins                react-dom.development.js:8299
(anonymous function)                    react-dom.development.js:8508
batchedEventUpdates$1                   react-dom.development.js:22396
batchedEventUpdates                     react-dom.development.js:3745
dispatchEventForPluginEventSystem       react-dom.development.js:8507
attemptToDispatchEvent                  react-dom.development.js:6005
dispatchEvent                           react-dom.development.js:5924
unstable_runWithPriority                scheduler.development.js:646
runWithPriority$1                       react-dom.development.js:11276
discreteUpdates$1                       react-dom.development.js:22413
discreteUpdates                         react-dom.development.js:3756
dispatchDiscreteEvent                   react-dom.development.js:5889

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. Cflux

    Хотя я не знаю, что вызывает ошибку, но я уверен, что эта функция имеет ошибку.

    sendEmail({
            name: nameRef.current.value,
            email: emailRef.current.value,
            message: messageRef.current.value
        }).then(result => {
            console.log("contact-us message sent with " + result.data.message)            
        })
            .catch(error => {
                console.log(error);                
            });
    
        history.push("/ContactUs") //<=== this is being called before sendMail is completed.
        setLoading(false)
    

    Возможно, вам стоит попробовать этот код.

       try {
         const results = await sendEmail({
                name: nameRef.current.value,
                email: emailRef.current.value,
                message: messageRef.current.value
            })
        console.log("contact-us message sent with " + result.data.message)  
        setLoading(false)
        history.push("/ContactUs") //<-- now this will be called properly.
        } catch (err) {
           console.log('error', error)
        }
    

    Другая проблема — ваш ref, вам нужно использовать ref.current вместо ref. См. sendEmail

    Функции Firebase

    Поскольку вы используете firebase.functions().httpsCallable, убедитесь, что вы используете .onCall() вместо onRequest().

    Я попробовал ваше предложение в моем async function handleSubmit(e), но все равно получил ту же ошибку. кажется, завис на линии const result =. person Cflux; 16.05.2021

    обновить ответ. следует использовать nameRef.current, а не просто nameRef. Пожалуйста, console.log все ваши ссылки, чтобы убедиться, что вы получаете нужные значения (строки), прежде чем отправлять через sendMail person Cflux; 16.05.2021

    @somoneSpecial, я обновил свой пост и теперь показывает новую ошибку. хороший звонок на консоли, регистрирующий ссылки. Мне пришлось сделать ref.current.value, чтобы получить желаемые значения. Если я просто сделаю ref.current, я получу [object HTMLInputElement] в консоли. person Cflux; 16.05.2021

    Возможно, вам придется создать новый вопрос, ваша новая ошибка, похоже, связана с вашими функциями Google. В то же время, можете ли вы отловить ошибку при вызове функции sendmail? person Cflux; 16.05.2021

    В ваших функциях firebase вы использовали .onRequest или .onCall? person Cflux; 16.05.2021

    это вызов .onRequest. Я задам еще один вопрос и разместлю ссылку здесь person Cflux; 17.05.2021

    вам следует использовать .onCall, поскольку вы используете httpsCallable. Узнайте, как записывать возвращаемые значения для функций httpCallable — firebase.google.com/docs/functions/ вызываемый person Cflux; 17.05.2021

    отлично сработано. Наверное, так. Я изучаю это. если вы хотите опубликовать это как ответ, я могу отметить его правильным, чтобы отдать должное. person Cflux; 17.05.2021

    в итоге добился некоторого прогресса и создал еще один вопрос person Cflux; 17.05.2021

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: