Formik,Material UI Autocomplete和Firestore-查询以查找数组参数

如何解决Formik,Material UI Autocomplete和Firestore-查询以查找数组参数

您如何修改formik onChange处理程序,以使其仅保存传递给Material UI自动完成字段的选项的值(而不是值加标签的数组)?

我有一个集合,该集合包含一个带有名为category的属性的文档。当前,该类别同时使用表单输入选项中的标签和值填充。

enter image description here

我正在努力寻找一种获取firebase的方法,以便在其中查询以找到数组的value属性。

我想知道如果我尝试仅将值而不是将标签和值保存到Firestore中,是否会更接近可行的解决方案。

我有一个Formik表格,其中:

import React,{ useState } from "react";
import ReactDOM from "react-dom";
import {render} from 'react-dom';

import { Link  } from 'react-router-dom';
import firebase,{firestore} from '../../../firebase';
import { withStyles } from '@material-ui/core/styles';

import {
  Button,LinearProgress,MenuItem,FormControl,Divider,InputLabel,FormControlLabel,TextField,Typography,Box,Grid,Dialog,DialogActions,DialogContent,DialogContentText,DialogTitle,} from '@material-ui/core';
import MuiTextField from '@material-ui/core/TextField';


import {
  Formik,Form,Field,ErrorMessage,FieldArray,} from 'formik';


import * as Yup from 'yup';
import {
  Autocomplete,ToggleButtonGroup,AutocompleteRenderInputParams,} from 'formik-material-ui-lab';
import {
  fieldToTextField,TextFieldProps,Select,Switch,CheckboxWithLabel,Checkbox
} from 'formik-material-ui';


const allCategories = [
    {value: 'health',label: 'Health & Medical'},{value: 'general',label: 'General'},];


function UpperCasingTextField(props: TextFieldProps) {
    const {
      form: {setFieldValue},field: {name},} = props;
    const onChange = React.useCallback(
      event => {
        const {value} = event.target;
        setFieldValue(name,value ? value.toUpperCase() : '');
      },[setFieldValue,name]
    );
    return <MuiTextField {...fieldToTextField(props)} onChange={onChange} />;
  }

  function Summary(props) {
    const { classes } = props;
    const [open,setOpen] = useState(false);
    const [isSubmitionCompleted,setSubmitionCompleted] = useState(false);
    
    function handleClose() {
      setOpen(false);
    }
  
    function handleClickOpen() {
      setSubmitionCompleted(false);
      setOpen(true);
    }
  
    return (
      <React.Fragment>
          <Button
              // component="button"
              color="primary"
              onClick={handleClickOpen}
              style={{ float: "right"}}
              variant="outlined"
          >
              Create 
          </Button>
        <Dialog
          open={open}
          onClose={handleClose}
          aria-labelledby="form-dialog-title"
        >
          {!isSubmitionCompleted &&
            <React.Fragment>
              
              <DialogContent>
                <Formik
                  initialValues={{ title: "",category: [],subcategory: "" }}
                  
                  onSubmit={(values,{ setSubmitting }) => {
                     setSubmitting(true);
                     
                 
    firestore.collection("study").doc().set({
                      ...values,createdAt: firebase.firestore.FieldValue.serverTimestamp()
                      })
                    .then(() => {
                      setSubmitionCompleted(true);
                    });
                  }}
  
                  validationSchema={Yup.object().shape({
                    title: Yup.string()
                      .required('Required'),category: Yup.string()
                      .required('Required'),})}
                >
                  {(props) => {
                    const {
                      values,touched,errors,dirty,isSubmitting,handleChange,handleBlur,handleSubmit,handleReset,} = props;
                    return (
                      <form onSubmit={handleSubmit}>
                        <TextField
                          label="Title"
                          name="title"
                          //   className={classes.textField}
                          value={values.title}
                          onChange={handleChange}
                          onBlur={handleBlur}
                          helperText={(errors.title && touched.title) && errors.title}
                          margin="normal"
                          style={{ width: "100%"}}
                        />

                        
                        <Box margin={1}>
                          <Field
                            name="category"
                            multiple
                            component={Autocomplete}
                            options={allCategories}
                            // value={values.label}
                            // value={values.value}
                            // value={allCategories.value} 
                           // value={values.category.allCategories.value}

我尝试了这些尝试中的每一次(一次) 仅填充一个字段-但它们都不起作用 那。相反,firebase会在其数组中记录标签和值。

                            getOptionLabel={(option: any) => option.label}
                            style={{width: '100%'}}
                            renderInput={(params: AutocompleteRenderInputParams) => (
                              <MuiTextField
                                {...params}
                                error={touched['autocomplete'] && !!errors['autocomplete']}
                                helperText={touched['autocomplete'] && errors['autocomplete']}
                                label="Category"
                                variant="outlined"
                              />
                            )}
                          />
                        </Box> 
                        
                        
                        <TextField
                          label="Subcategory "
                          name="subcategory"
                          //   className={classes.textField}
                          value={values.subcategory}
                          onChange={handleChange}
                          onBlur={handleBlur}
                          helperText={(errors.subcategory && touched.subcategory) && errors.subcategory}
                          margin="normal"
                          style={{ width: "100%"}}
                        />
  
                        
                      
                        <DialogActions>
                          <Button
                            type="button"
                            className="outline"
                            onClick={handleReset}
                            disabled={!dirty || isSubmitting}
                          >
                            Reset
                          </Button>
                          <Button type="submit" disabled={isSubmitting}>
                            Submit
                          </Button>
                          {/* <DisplayFormikState {...props} /> */}
                        </DialogActions>
                      </form>
                    );
                  }}
                </Formik>
              </DialogContent>
            </React.Fragment>
          }
          {isSubmitionCompleted &&
            <React.Fragment>
              <DialogTitle id="form-dialog-title">Done!</DialogTitle>
              <DialogContent>
               
                <DialogActions>
                  <Button
                    type="button"
                    className="outline"
                    onClick={handleClose}
                  >
                    Close
                    </Button>
                  {/* <DisplayFormikState {...props} /> */}
                </DialogActions>
              </DialogContent>
            </React.Fragment>}
        </Dialog>
      </React.Fragment>
    );
  }

export default Summary;

然后,当我尝试查询Firebase时,我正在尝试查找类别包括健康状况的文档。

我已经尝试了下面的每个where查询,但我无法让它们返回查询的结果(如果删除了where查询,则可以返回所有结果):

function useHealthTerms() {
    const [healthTerms,setHealthTerms] = useState([])
    useEffect(() => {
      firebase
        .firestore()
        .collection("study")
    //.where("title","==","ss") 

注意-这可以找到标题。标题字段相同 级别作为类别字段

        //.where('category','==','health')
        //.where('category.value',"array-contains",'health")
        //.where('category','array-contains','health')
        //.where('category',1)
    //.where("category.1.value",'health')
        .onSnapshot(snapshot => {
          const healthTerms = snapshot.docs.map(doc => ({
            id: doc.id,...doc.data(),}))
          setHealthTerms(healthTerms)
        })
    },[])
    return healthTerms
  }

我见过this post,但是我不够聪明,无法从答案中获得任何意义。

我也看到了this post和贝蒂建议的答案。我对以下查询构造尝试了多种变体,以尝试使用该想法,但是每次,查询形式都会出错。

.where(new firebase.firestore().FieldPath("category","value"),'health')

我想知道是否可以尝试在formik中获取类别表单字段,只是为了保存option.value而不是标签和值。

我看不到formik handleChange如何工作以要求它仅保存值。

即使那样,我也看不到如何查询firestore来将数组的内容用作查询参数。

有人知道吗?

  1. 如何通过Formik表单提交到Firestore仅在自动完成中保存选项值(而不是选项标签和值)?

  2. 如何在Firestore中查询数组的内容,以查看其属性之一是否与查询匹配?

这很奇怪,因为this post建议使用上面我尝试过的形式对数组进行where查询。但是,这篇文章建议使用以下格式.collection(study / [docId])。where(“ value”,“ ==”,“ health”)。我需要它来搜索集合中的每个文档,所以我不知道如何将这种方法应用于此问题。

下面来自gso_gabriel的答案提出了两个令人困惑的事情。首先,假设我使用了一个子集合。我没有在父文档中添加以下图片以显示类别字段。我可以使用上面显示的格式对标题进行where查询,以提取值。

enter image description here

其次,最令人困惑的是-它说:“因为您无法在数组内搜索对象”。这是什么意思?是否暗示不能对类别字段中的值的内容执行查询?如果是这样,是否有资源提供有关如何查询此数据的指南?

我还看到了this post-的答案表明,使用Firebase无法查询类别内的值。问题是我无法理解建议的替代方法。如果我正确理解了这篇文章,是否有任何教程对原理进行了扩展,以便我可以尝试找到其他查询策略?

this post的第一个答案还表明,无法查询类别内的值。第二个答案建议在where查询中使用其他格式-如下。

.where("category",{value: "health",label: "Health & Medical"})

答案强调了将整个数组内容添加到花括号的重要性。这行得通。

所以-这使我回到了自动完成提交处理程序。这是一个多选字段,因此可能选择了多个值。如何在Firebase文档上将它们变成一组单个值。即使只有一个,如何更改提交处理程序,使其仅发送选择选项值,而不是同时发送值和标签?

如果不可能查询数组中的对象-如何更改提交处理程序以仅将选定的选项值添加到firebase中,而不是标签和值中?对this post的第一个答案中建议的解决方法是添加一个仅包含要查询的值的字段(因此:health)。

解决方法

在通过onSubmit提交到Firebase之前,您可以更改发送数据的形状

onSubmit={(values,{ setSubmitting }) => {
    setSubmitting(true);

    firestore.collection("study").doc().set({
     ...values,category: values.category.map(c => c.value),createdAt: firebase.firestore.FieldValue.serverTimestamp()
    })
    .then(() => {
        setSubmitionCompleted(true);
    });
}}
,

我将通过逐一回答您的观点来尝试澄清您的疑问。

  • 要仅保存value,就需要更改将信息发送到Firestore的方式。更改您的values变量,因为该变量也要维护label中的值。总而言之,在与Firestore相关时,您需要基本更改代码,在其中使用label值进行变量。
  • 澄清您提到的here帖子-通常,NoSQL数据库是根据查询方式创建的。因此,您将首先根据需要使用这些查询以及对数据库的结构进行正确处理,这样就不会遇到任何问题。确实,由于您无法在Array中搜索对象,因此,我认为重组方案是最佳选择。
  • 也许可以使用本示例中阐明的子集合here可能会帮助您简化工作。

更改将是最适合您的选择,因此您可以拥有一个完全适合您的查询和需求的方案-这是NoSQL的许多优点之一,可以自由地创建方案。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-