首页 > 解决方案 > 在 React.js 中点击动画表单提交通知

问题描述

我正在使用自定义联系表单创建一个 React 应用程序。一切正常,除了我不确定如何在通知已发送消息的情况下淡入和超时块。

在这里你可以看到我的代码:

const Contact = () => {
const [notice, setNotice] = useState(false);
const handleSubmit = async (e) => {
    e.preventDefault();
    const { name, surname, phone, email, message } = e.target.elements;
    let details = {
      name: name.value,
      surname: surname.value,
      phone: phone.value,
      email: email.value,
      message: message.value,
    };
    let response = await fetch("http://localhost:5000/contact", {
      method: "POST",
      headers: {
        "Content-Type": "application/json;charset=utf-8",
      },
      body: JSON.stringify(details),
    });
    let result = await response.json();
    setNotice(result.status);
    e.target.reset();
 }
}
<div className="notice">{notice}</div>

标签: javascriptcssreactjsformscss-animations

解决方案


您可以为此使用自定义挂钩,它使用setTimeout计时器在指定时间后消失。下面的示例useNotification()返回一个显示消息的组件和一个可用于触发通知出现的回调。

function useNotification() {
  const [message, setMessage] = React.useState(null);

  // runs when message state changes
  React.useEffect(() => {
    // if there is no message, don't run anything below this
    if (!message) { return; }

    // start a 5 sec timer and reset the message state when it expires
    const timer = window.setTimeout(() => setMessage(null), 5000);

    // the returned function runs on unmount
    return () => {
      window.clearTimeout(timer);
    };
  }, [message]);

  // call this with the message to update state
  // once the state is updated, the function in useEffect hook above runs
  function addNotification(notification) {
    setMessage(notification);
  }

  // component to display the notification message
  function Notification() {
    return (
      <div className="notification" role="alert">
        {message && <div className="notification-content">{message}</div>}
      </div>
    );
  }

  // return the component to display the message, and a callback to trigger
  return [Notification, addNotification];
}

查看下面的工作演示:

function useNotification() {
  const [message, setMessage] = React.useState(null);
  const [messageType, setMessageType] = React.useState('info');
  const DELAY = 5000;

  React.useEffect(() => {
    if (!message) { return; }

    const timer = window.setTimeout(() => setMessage(null), DELAY);

    return () => {
      window.clearTimeout(timer);
    };
  }, [message]);

  function addNotification(notification, type = 'info') {
    setMessage(notification);
    setMessageType(type);
  }

  function Notification() {
    return (
      <div className={`notification notification-${messageType}`} role="alert">
        {message && <div className="notification-content">{message}</div>}
      </div>
    );
  }

  return [Notification, addNotification];
}

function ContactForm({ addNotification }) {
  const [email, setEmail] = React.useState('terry@site.io');
  const [name, setName] = React.useState('Terry');
  const [message, setMessage] = React.useState("Don't you love React?!");
  const [error, setError] = React.useState(false);

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

    // send message...

    // display notification
    if (error) {
      addNotification('Something went wrong. Try again!', 'error');
    } else {
      addNotification(`Thanks for your message, ${name}!`, 'success');
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input
          type="text"
          required
          onChange={(e) => setName(e.target.value)}
          value={name}
        />
      </label>
      <label>
        Email:
        <input
          type="email"
          required
          onChange={(e) => setEmail(e.target.value)}
          value={email}
        />
      </label>
      <label>
        Message:
        <textarea
          required
          onChange={(e) => setMessage(e.target.value)}
          value={message}
        />
      </label>
      <label className="checkbox">
        <input
          type="checkbox"
          checked={error}
          onChange={(e) => setError(e.target.checked)}
        />
        Click this to see error message
      </label>
      <button type="submit">Send message</button>
    </form>
  );
}

function App() {
  const [Notification, addNotification] = useNotification();

  return (
    <div className="wrapper">
      <ContactForm addNotification={addNotification} />
      <Notification />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
* {
  box-sizing: inherit;
}

body {
  box-sizing: border-box;
  color: #554f4f;
  font-family: sans-serif;
  font-size: 18px;
  line-height: 1.4;
  margin: 0;
}

.wrapper {
  margin: 0 auto;
  max-width: 400px;
  padding: 1rem;
}

button,
input,
textarea {
  border: 3px solid #ccc;
  border-radius: 4px;
  color: inherit;
  display: block;
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  margin: 0.25rem 0 1rem;
  padding: 0.5rem;
  width: 100%;
}

button {
  background-color: #333;
  border: 0;
  color: #fff;
  cursor: pointer;
  padding: 1rem;
}

.checkbox {
  display: flex;
}

input[type="checkbox"] {
  margin-left: 1rem;
  margin-right: 1rem;
  transform: scale(1.5);
  width: auto;
}

.notification {
  animation: fadein 0.3s ease-in-out;
  background-color: #c8d8ff;
  border-radius: 4px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.07);
  color: rgba(0, 0, 0, 0.75);
  text-align: center;
}

.notification-error {
  background-color: #f9c5c5;
}

.notification-success {
  background-color: #d9f59f;
}

.notification-content {
  padding: 1rem;
}

@keyframes fadein {
  from {
    opacity: 0;
    transform: translateY(-20%);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>


推荐阅读