首页 > 解决方案 > 表单呈现在模态之外

问题描述

我的模态有问题。模态内部的表单在模态本身之外呈现。我已经尝试在没有任何更改的情况下编辑 CSS 的显示设置,以及切换到 react-bootstrap 而不是常规引导。我不确定我接下来的步骤。

我是 React 和 TypeScript 的新手,让我知道我可以做些什么来解决这个问题,当然,如果有任何知识需要学习,我全力以赴!

app.tsx - 应用程序的核心

import React, { useRef, useState } from 'react';

import { useAuthState } from 'react-firebase-hooks/auth';
import { useCollectionData } from 'react-firebase-hooks/firestore';
import { auth, firestore } from './components/firebase';
import { GoogleSignIn } from './components/google-sign-in';
import { SignOut } from './components/sign-out';

import { Modal } from 'react-bootstrap';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import Col from 'react-bootstrap/Col';

import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
import './App.css';

function App() {
  const [user] = useAuthState(auth);

  return (
    <>
      <div className="App">
        <header>
          <h2> CHEESE </h2>
          <small>Presented by Pixel Network</small>
          <SignOut />
        </header>
        <section>
          <SignUp />
          {user ? <ChatRoom /> : <GoogleSignIn />}
        </section>
      </div>
    </>
  );
}

function RegistrationModal(props:any) {
  const [state, setState] = useState ({
    email : "",
    password: "",
    confirmPassword: ""
  })
  const handleChange = (e:any) => {
    const { id, value } = e.target
    setState(prevState => ({
      ...prevState,
      [id] : value
    }))
  }
  const handleSubmitClick = (e:any) => {
    e.preventDefaults();
    if (state.password === state.confirmPassword) {
      firebase.auth().createUserWithEmailAndPassword(state.email, state.password)
        .then((user) => {
          // Signed in
          // ...
        })
        .catch((error) => {
          var errorCode = error.code;
          var errorMessage = error.message;
          console.log(errorCode + " : " + errorMessage)
        });
    } else {
      props.showError('Passwords do not match');
    }
  }

  return (
    <>
    <Modal
      {...props}
      size="lg"
      aria-labelledby="contained-modal-title-vcenter"
      centered
    >
      <Modal.Header closeButton>
        <Modal.Title>Register</Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <Form>
          <Form.Row className="align-items-center">
            <Col xs="auto">
              <Form.Label htmlFor="inlineFormInput" srOnly />
              <Form.Control 
                type="email"
                aria-describedby="emailHelp"
                placeholder="Enter email"
                value={state.email}
                onChange={handleChange}
              />
            </Col>
            <Col xs="auto">
              <Form.Label htmlFor="inlineFormInput" srOnly />
              <Form.Control 
                type="password"
                placeholder="Enter password"
                value={state.password}
                onChange={handleChange}
              />
            </Col>
            <Col xs="auto">
              <Form.Label htmlFor="inlineFormInput" srOnly />
              <Form.Control 
                type="password"
                placeholder="Confirm password"
                value={state.confirmPassword}
                onChange={handleChange}
              />
            </Col>
          </Form.Row>
        </Form>
      </Modal.Body>
      <Modal.Footer>
        <Button type="submit" onClick={handleSubmitClick}>Submit</Button>
        <Button onClick={props.onHide}>Close</Button>
      </Modal.Footer>
    </Modal>
    </>
  )
}

function SignUp() {
  const [modalShow, setModalShow] = React.useState(false);
  
  return (
    <>
      <Button variant="primary" onClick={() => setModalShow(true)}>
        Register with Email
      </Button>

      <RegistrationModal
        show={modalShow}
        onHide={() => setModalShow(false)}
      />
    </>
  )
}

function ChatRoom() {
  const dummy = useRef<HTMLDivElement>(null);
  const messagesRef = firestore.collection('messages');
  const query = messagesRef.orderBy('createdAt').limit(25);
  
  const [messages] = useCollectionData(query, { idField: 'id' });
  const [formValue, setFormValue] = useState('');

  const sendMessage = async (e:any) => {
    e.preventDefault();

    const user = auth.currentUser;
    if (user) {
      const { uid, photoURL } = user;

      await messagesRef.add ({
        text: formValue,
        createdAt: firebase.firestore.FieldValue.serverTimestamp(),
        uid,
        photoURL
      });
      setFormValue('');
      dummy.current!.scrollIntoView({ behavior: 'smooth' });
    } else {
      try {
        // Signs user out - hopefully fixing error on next authenticate
        auth.signOut();
      }
      catch (e) {
        console.log('Error:', e);
      }
    };
  }
  return (
    <>
    <main>
      {messages && messages.map((msg:any) => <ChatMessage key={msg.id} message={msg} />)}
      <span ref={dummy}></span>
    </main>
    <form onSubmit={sendMessage}>
      <input value={formValue} onChange={(e) => setFormValue(e.target.value)} placeholder="Type here..." />
      <button type="submit" disabled={!formValue}>️&lt;/button>
    </form>
    </>
  );
}

function ChatMessage(props:any) {
  const { text, uid, photoURL } = props.message;
  const messageClass = uid === auth.currentUser!.uid ? 'sent' : 'received';
  
  return (
    <>
      <div className={`message ${messageClass}`}>
        <img src={photoURL || 'https://api.hello-avatar.com/adorables/myseed'} alt={text} />
        <p>{text}</p>
      </div>
    </>
  );
}

export default App;

注册模式(功能) - 模式和表单所在的位置

function RegistrationModal(props:any) {
  const [state, setState] = useState ({
    email : "",
    password: "",
    confirmPassword: ""
  })
  const handleChange = (e:any) => {
    const { id, value } = e.target
    setState(prevState => ({
      ...prevState,
      [id] : value
    }))
  }
  const handleSubmitClick = (e:any) => {
    e.preventDefaults();
    if (state.password === state.confirmPassword) {
      firebase.auth().createUserWithEmailAndPassword(state.email, state.password)
        .then((user) => {
          // Signed in
          // ...
        })
        .catch((error) => {
          var errorCode = error.code;
          var errorMessage = error.message;
          console.log(errorCode + " : " + errorMessage)
        });
    } else {
      props.showError('Passwords do not match');
    }
  }

  return (
    <>
    <Modal
      {...props}
      size="lg"
      aria-labelledby="contained-modal-title-vcenter"
      centered
    >
      <Modal.Header closeButton>
        <Modal.Title>Register</Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <Form>
          <Form.Row className="align-items-center">
            <Col xs="auto">
              <Form.Label htmlFor="inlineFormInput" srOnly />
              <Form.Control 
                type="email"
                aria-describedby="emailHelp"
                placeholder="Enter email"
                value={state.email}
                onChange={handleChange}
              />
            </Col>
            <Col xs="auto">
              <Form.Label htmlFor="inlineFormInput" srOnly />
              <Form.Control 
                type="password"
                placeholder="Enter password"
                value={state.password}
                onChange={handleChange}
              />
            </Col>
            <Col xs="auto">
              <Form.Label htmlFor="inlineFormInput" srOnly />
              <Form.Control 
                type="password"
                placeholder="Confirm password"
                value={state.confirmPassword}
                onChange={handleChange}
              />
            </Col>
          </Form.Row>
        </Form>
      </Modal.Body>
      <Modal.Footer>
        <Button type="submit" onClick={handleSubmitClick}>Submit</Button>
        <Button onClick={props.onHide}>Close</Button>
      </Modal.Footer>
    </Modal>
    </>
  )
}

App.css - 应用程序的样式

@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');

body {
  font-family: 'Roboto', sans-serif;
  background-color: #303030;
}
.App {
  text-align: center;
  max-width: 728px;
  margin: 0 auto;
}
.App header {
  background-color: #333333;
  height: 10vh;
  min-height: 50px;
  color: white;
  position: fixed;
  width: 100%;
  max-width: 728px;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  z-index: 99;
  padding: 10px;
  box-sizing: border-box;
}
.App section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100vh;
  background-color: #414141;
}
main {
  padding: 10px;
  height: 80vh;
  margin: 10vh 0 10vh;
  overflow-y: scroll;
  display: flex;
  flex-direction: column;
}
main::-webkit-scrollbar {
  width: 0.25rem;
}
main::-webkit-scrollbar-track {
  background: #333333;
}
main::-webkit-scrollbar-thumb {
  background: #333333;
}
form {
  height: 10vh;
  position: fixed;
  bottom: 0;
  width: 100%;
  max-width: 728px;
  display: flex;
  font-size: 1.5rem;
}
form button {
  width: 20%;
  background-color: #333333;
  border: 1px solid #333333;
}
form button:hover {
  background-color: #272727; 
}
input {
  line-height: 1.5;
  width: 100%;
  font-size: 1.5rem;
  background: #1f1f1f;
  color: white;
  outline: none;
  border: none;
  padding: 0 10px;
}
button {
  background-color: #fff;
  border: none;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  cursor: pointer;
  font-size: 1.25rem;
}
button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
ul, li {
  text-align: left;
  list-style: none;
}
p {
  max-width: 500px;
  margin-bottom: 12px;
  line-height: 24px;
  padding: 10px 20px;
  border-radius: 5px;
  position: relative;
  color: white;
  text-align: center;
}
.message {
  display: flex;
  align-items: center;
}
.sent {
  flex-direction: row-reverse;
}
.sent p {
  color: white;
  background: #00aeff;
  align-self: flex-end;
}
.received p {
  background: #e5e5ea;
  color: #333333;
}
img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin: 2px 5px;
}
.guideline {
  margin: 0 auto;
}
.btn-sign-in {
  background-color: #0051ff;
  color: white;
  max-width: 235px;
  margin: 0 auto;
}
.btn-sign-in:hover {
  color: white;
  background-color: #0f5bff;
}

截屏 错误截图

标签: javascriptreactjstypescriptfirebase

解决方案


form这是由我为元素编写的 CSS 引起的

我已更改此表单以包含一个类名<form className="messageForm" onSubmit={sendMessage}>

并将formCSS 更改为 -

form.message {
 height: 10vh;
 position: fixed;
 bottom: 0;
 width: 100%;
 max-width: 728px;
 display: flex;
 font-size: 1.5rem;
}

这已将 CSSform恢复为默认值


推荐阅读