You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Firebase日历应用点击按钮自动生成已填内容卡片功能咨询

问题描述

我开发了一款日历应用,页面下方设置了若干可填写的文本输入框。目前Firebase运行无异常,用户填写的所有内容都能正常存入数据库。我现在需要实现以下功能:用户填写完所有字段内容后点击提交按钮,即可自动生成卡片组件展示刚刚填写的内容。

操作页示意图如下:
输入页示意图

点击按钮后生成的卡片预期效果如下:
卡片效果示意图

当前项目相关代码如下:

import React, { useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import Card from "@material-ui/core/Card";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import { Checkbox, Container, Slide } from "@material-ui/core";
import Icon from "@material-ui/core/Icon";
import { StyleSheet } from "react-native";
import firebase from "firebase/app";
import "firebase/firestore";
import { db } from "../../firebase";
import { ScrollView } from "react-native-gesture-handler";

export default function DateAndTimePickers() {
  const classes = useStyles();
  const [ort, setOrt] = useState("");
  const [notiz, setNotiz] = useState("");
  const [hinweis, setHinweis] = useState("");
  const [eintragen, setEintragen] = useState([]);
  const [dateandtime, setDateandtime] = useState([]);

  function handelDateandTime(e) {
    setDateandtime(e.target.value);
  }
  function handelOrt(e) {
    setOrt(e.target.value);
  }
  function handelNotiz(e) {
    setNotiz(e.target.value);
  }
  function handelHinweis(e) {
    setHinweis(e.target.value);
  }
  function KalenderEintrag() {
    db.collection("Eintrag")
      .doc()
      .set({
        ort,
        notiz,
        hinweis,
        dateandtime,
      })
      .then(() => {
        //If you wish to push the written data to your local state, you can do it here
        setEintragen([...eintragen, { ort, notiz, hinweis, dateandtime }]);
        console.log("Documents saved succesfully");
      })
      .catch((err) => {
        console.log(err);
      });
  }
  return (
    <ScrollView style={styles.root}>
      <Container>
        <TextField
          id="datetime-local"
          label="Neues Ereigniss"
          type="datetime-local"
          defaultValue="2021-09-16T10:30"
          className={classes.root}
          InputLabelProps={{
            shrink: true,
          }}
          onChange={(value) => {
            handelDateandTime(value);
          }}
        />
      </Container>
      {/* ORT */}
      <Container className={classes.ortContainer}>
        <TextField
          id="standard-helperText"
          label="Ort"
          defaultValue="Text"
          onChange={(value) => {
            handelOrt(value);
          }}
        />
      </Container>
      {/* Hinweis */}
      <Container className={classes.ortContainer}>
        <TextField
          id="standard-helperText"
          label="Hinweis"
          defaultValue="Text"
          onChange={(value) => {
            handelHinweis(value);
          }}
        />
      </Container>
      {/* Notizen */}
      <Container className={classes.ortContainer}>
        <TextField
          id="standard-helperText"
          label="Notizen"
          defaultValue="Text"
          onChange={(value) => {
            handelNotiz(value);
          }}
        />
      </Container>
      

      <Container>
        <Button onClick={() => KalenderEintrag()}  className={classes.btn} variant="outlined">Absenden</Button>
      </Container>

      {/* Kalender einträge  */}
      <Card className={classes.card}>
        <CardContent>
          <Typography
            className={classes.title}
            color="textSecondary"
            gutterBottom
          >
            AUSFLUG
          </Typography>
          <Typography variant="h5" component="h2">
            Wilheminenberg
          </Typography>
          <Typography className={classes.pos} color="textSecondary">
            Jause wird mitgegeben
          </Typography>
          <Typography variant="body2" component="p">
            Am 13.9.21 von 09:00 - 13:00
            <br />
            {"Abholung erfolgt im KG"}
          </Typography>
        </CardContent>
        <CardActions>
          <Button size="small" variant="outlined">
            Zur Kenntniss genommen
          </Button>
        </CardActions>
      </Card>
    </ScrollView>
  );
}

//material UI style
const useStyles = makeStyles({
  root: {
    marginTop: 30,
    marginLeft: 16,
  },
  card: {
    marginTop: 30,
    marginLeft: 15,
    marginRight: 15,
  },
  bullet: {
    display: "inline-block",
    margin: "0 2px",
    transform: "scale(0.8)",
  },
  title: {
    fontSize: 14,
  },
  pos: {
    marginBottom: 12,
  },
  table: {
    marginTop: 30,
  },
  ortContainer: {
    marginTop: 30,
    marginLeft: 15,
    marginRight: 15,
  },
  btn:{
    marginTop: 20,
    marginLeft: 15,
  }
});

//React native style
const styles = StyleSheet.create({
  root: {
    backgroundColor: "white",
  },
});
解决方案

你已经实现了提交数据同步到本地eintragen状态的逻辑,只需将写死的示例卡片替换为遍历eintragen数组渲染动态卡片即可,同时修复几个代码小问题优化使用体验:

  1. 修正dateandtime初始值错误,应该是字符串类型不是数组
  2. 简化输入框onChange回调,无需额外嵌套箭头函数
  3. 提交成功后清空输入框
  4. 新增时间格式化函数,将datetime-local的原始输出转换为你需要的展示格式

修改后的完整代码如下:

import React, { useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import Card from "@material-ui/core/Card";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import { Checkbox, Container, Slide } from "@material-ui/core";
import Icon from "@material-ui/core/Icon";
import { StyleSheet } from "react-native";
import firebase from "firebase/app";
import "firebase/firestore";
import { db } from "../../firebase";
import { ScrollView } from "react-native-gesture-handler";

export default function DateAndTimePickers() {
  const classes = useStyles();
  const [ort, setOrt] = useState("");
  const [notiz, setNotiz] = useState("");
  const [hinweis, setHinweis] = useState("");
  const [eintragen, setEintragen] = useState([]);
  // 修正初始值为字符串
  const [dateandtime, setDateandtime] = useState("");

  function handelDateandTime(e) {
    setDateandtime(e.target.value);
  }
  function handelOrt(e) {
    setOrt(e.target.value);
  }
  function handelNotiz(e) {
    setNotiz(e.target.value);
  }
  function handelHinweis(e) {
    setHinweis(e.target.value);
  }
  function KalenderEintrag() {
    db.collection("Eintrag")
      .doc()
      .set({
        ort,
        notiz,
        hinweis,
        dateandtime,
      })
      .then(() => {
        setEintragen([...eintragen, { ort, notiz, hinweis, dateandtime }]);
        console.log("Documents saved succesfully");
        // 提交后清空输入框
        setOrt("");
        setNotiz("");
        setHinweis("");
        setDateandtime("");
      })
      .catch((err) => {
        console.log(err);
      });
  }

  // 时间格式化函数
  const formatDate = (dateStr) => {
    const date = new Date(dateStr);
    const year = date.getFullYear().toString().slice(2);
    const month = date.getMonth() + 1;
    const day = date.getDate();
    const hour = date.getHours().toString().padStart(2, '0');
    const minute = date.getMinutes().toString().padStart(2, '0');
    return `Am ${day}.${month}.${year} von ${hour}:${minute}`
  }

  return (
    <ScrollView style={styles.root}>
      <Container>
        <TextField
          id="datetime-local"
          label="Neues Ereigniss"
          type="datetime-local"
          value={dateandtime}
          className={classes.root}
          InputLabelProps={{
            shrink: true,
          }}
          onChange={handelDateandTime}
        />
      </Container>
      {/* ORT */}
      <Container className={classes.ortContainer}>
        <TextField
          id="standard-helperText"
          label="Ort"
          value={ort}
          onChange={handelOrt}
        />
      </Container>
      {/* Hinweis */}
      <Container className={classes.ortContainer}>
        <TextField
          id="standard-helperText"
          label="Hinweis"
          value={hinweis}
          onChange={handelHinweis}
        />
      </Container>
      {/* Notizen */}
      <Container className={classes.ortContainer}>
        <TextField
          id="standard-helperText"
          label="Notizen"
          value={notiz}
          onChange={handelNotiz}
        />
      </Container>
      
      <Container>
        <Button onClick={KalenderEintrag}  className={classes.btn} variant="outlined">Absenden</Button>
      </Container>

      {/* 动态渲染所有提交的卡片 */}
      {eintragen.map((item, index) => (
        <Card key={index} className={classes.card}>
          <CardContent>
            <Typography
              className={classes.title}
              color="textSecondary"
              gutterBottom
            >
              EREIGNIS
            </Typography>
            <Typography variant="h5" component="h2">
              {item.ort}
            </Typography>
            <Typography className={classes.pos} color="textSecondary">
              {item.hinweis}
            </Typography>
            <Typography variant="body2" component="p">
              {formatDate(item.dateandtime)}
              <br />
              {item.notiz}
            </Typography>
          </CardContent>
          <CardActions>
            <Button size="small" variant="outlined">
              Zur Kenntniss genommen
            </Button>
          </CardActions>
        </Card>
      ))}
    </ScrollView>
  );
}

//material UI style
const useStyles = makeStyles({
  root: {
    marginTop: 30,
    marginLeft: 16,
  },
  card: {
    marginTop: 30,
    marginLeft: 15,
    marginRight: 15,
  },
  bullet: {
    display: "inline-block",
    margin: "0 2px",
    transform: "scale(0.8)",
  },
  title: {
    fontSize: 14,
  },
  pos: {
    marginBottom: 12,
  },
  table: {
    marginTop: 30,
  },
  ortContainer: {
    marginTop: 30,
    marginLeft: 15,
    marginRight: 15,
  },
  btn:{
    marginTop: 20,
    marginLeft: 15,
  }
});

//React native style
const styles = StyleSheet.create({
  root: {
    backgroundColor: "white",
  },
});

内容的提问来源于stack exchange,提问作者chin14

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 22:45:01