【问题标题】:How do I add a loading spinner in React and Node app? (Nodemailer)如何在 React 和 Node 应用程序中添加加载微调器? (节点邮件程序)
【发布时间】:2020-08-21 17:06:06
【问题描述】:

我想实现类似当我单击发送按钮时,按钮附近应该出现一个微调器,然后将发送按钮转换为消息发送按钮。我可以实现按钮更改,但没有加载时间。为什么会立即发生?

反应前端:

import React from 'react';
import './contact.css';
import tick4 from './tick4.svg';
import copy from './copy.svg';
import axios from 'axios';

class Contact extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: '',
            email: '',
            phone: '',
            loading: false,
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange = (e) => {
        this.setState({ [e.target.name]: e.target.value });
    };

    handleSubmit(e) {
        e.preventDefault();

        const { name, email, phone } = this.state;

        axios.post('/api/contact', {
            name,
            email,
            phone,
        });

        this.resetForm();
    }

    resetForm() {
        this.setState({ name: '', email: '', phone: '', loading: true });
    }

    render() {
        return (
            <div className="contact">
                <div className="contact-flex">
                    <div className="contact-right">
                        <h1>GET IN TOUCH</h1>
                        <div>
                            <form onSubmit={this.handleSubmit} method="POST">
                                <label htmlFor="name">NAME</label>
                                <br />
                                <input
                                    onChange={this.handleChange}
                                    value={this.state.name}
                                    type="text"
                                    id="name"
                                    name="name"
                                    placeholder="Your full name..."
                                    required
                                />
                                <br />

                                <label htmlFor="phone">PHONE</label>
                                <br />
                                <input
                                    onChange={this.handleChange}
                                    type="text"
                                    id="phone"
                                    name="phone"
                                    placeholder="Your phone number..."
                                    value={this.state.phone}
                                    required
                                />
                                <br />

                                <label htmlFor="email">EMAIL</label>
                                <br />
                                <input
                                    onChange={this.handleChange}
                                    type="email"
                                    id="email"
                                    name="email"
                                    placeholder="Your email address..."
                                    value={this.state.email}
                                    required
                                />
                                <br />

                                {!this.state.loading && (
                                    <button className="contact-button" type="submit">
                                        Send
                                    </button>
                                )}

                                {this.state.loading && (
                                    <button className="contact-button" type="submit">
                                        Message Sent
                                    </button>
                                )}
                            </form>
                        </div>
                    </div>
                </div>
                <div className="copy">
                    <img src={copy} className="copysvg" alt="copy"></img>
                </div>
            </div>
        );
    }
}

export default Contact;

节点后端(Nodemailer):

var express = require('express');
const bodyParser = require('body-parser');
var nodemailer = require('nodemailer');
const creds = require('./config');

const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.post('/api/contact', (req, res) => {
    nodemailer.createTestAccount((err, account) => {
        const htmlEmail = `
            Name: ${req.body.name}
            Phone: ${req.body.phone}
            Email: ${req.body.email}
        `;

        let transporter = nodemailer.createTransport({
            host: 'smtp.ethereal.email',
            port: 587,
            auth: {
                user: 'MYEMAILHERE',
                pass: 'MYPASSWORDHERE',
            },
        });

        let mailOptions = {
            from: req.body.name,
            to: 'TOTHISEMAIL',
            subject: 'Potential Client Message From The Workshop',
            html: htmlEmail,
        };

        transporter.sendMail(mailOptions, (err, data) => {
            console.log('message sent');
        });
    });
});

const PORT = process.env.PORT || 3001;

app.listen(PORT, () => {
    console.log(`server listening on port ${PORT}`);
});

【问题讨论】:

  • 您可以将 async/await 添加到您的函数 `async handleSubmit(e)` 中,在沙之前,您应该将 loading 状态设置为 true 并在 await axios.post('/api/contact' 之后将 loading 状态设置为 @ 987654327@ 接下来你可以使用loading state 在你的jsx代码中显示条件
  • 也说明你知道用来显示按钮的东西,你可以重命名为isDataSent
  • 感谢您的快速回复。我稍后会检查并回来。现在AFK。 :)

标签: html node.js reactjs express axios


【解决方案1】:

浏览器中的 Javascript 是异步的,所以当你发布请求时,当你得到结果时 this.resetForm 函数已经被调用了

对代码进行以下更改:

toggleLoading = () => {
    this.setState(prevState => {
        loading: !prevState.loading
    })
}

handleSubmit(e) {
    e.preventDefault();
    const { name, email, phone } = this.state;
    this.toggleLoading()
    axios.post('/api/contact', {
        name,
        email,
        phone,
    })
    .then(result => {
        this.resetForm();
        //something
    })
    .catch(err => {
        //something
        this.toggleLoading()
    });
}

resetForm() {
    this.setState({ name: '', email: '', phone: '', loading: false });
}

注意:在 resetForm 中将加载更改为 false

建议: 您无需写入按钮即可保存。就这样做

<button className="contact-button" type="submit">
    {this.state.loading ? 'Saving...' : 'Send'}
</button>

你不需要这个

 this.handleChange = this.handleChange.bind(this);

如果你使用的是箭头函数,除非你使用的是非常旧的 react 版本

【讨论】:

  • 感谢您的全面而快速的评论。我稍后会检查并回复。现在AFK。 :)
  • 您还需要添加新状态,如已发送:真/假,成功时使状态为真并相应地显示消息。有很多方法可以做到这一点。只是一个建议
猜你喜欢
  • 1970-01-01
  • 2021-03-19
  • 1970-01-01
  • 2014-03-03
  • 2021-06-06
  • 1970-01-01
  • 2020-01-30
  • 1970-01-01
  • 2018-05-16
相关资源
最近更新 更多