【问题标题】:How do I change a Formik TextField value from the outside of the From?如何从 From 外部更改 Formik TextField 值?
【发布时间】:2020-08-01 13:45:22
【问题描述】:

在模块对话框中,我想更改输入值 (#quaggaIsbn) 的值。我试过document.getElementById("quaggaIsbn").value = result.codeResult.code,但它没有反映到表单发送到服务器的值上。如何更改 Formik 发送到服务器的值?

NewProjectDialog.js

import React from 'react';
import PropTypes from 'prop-types'
import { Formik, Field, Form } from 'formik'
import { TextField} from 'formik-material-ui'
import { makeStyles } from '@material-ui/core/styles'
import Button from '@material-ui/core/Button'
import Dialog from '@material-ui/core/Dialog'
import DialogTitle from '@material-ui/core/DialogTitle'
import DialogActions from '@material-ui/core/DialogActions'
import DialogContent from '@material-ui/core/DialogContent'
import styles from './NewProjectDialog.styles'
import Quagga from 'quagga';

const useStyles = makeStyles(styles)

function NewProjectDialog({ onSubmit, open, onRequestClose }) {
  const classes = useStyles()

  function handleSubmit(values, { setSubmitting }) {
    return onSubmit(values).then(() => {
      setSubmitting(false)
    })
  }



  function inputFile(){
    const file = document.getElementById("quaggaFile").files[0];
    const reader = new FileReader();
    reader.addEventListener("load", function () {
      // convert image file to base64 string
      analyzeQuaggaFile(reader.result);
      //preview.src = reader.result;
    }, false);
    reader.readAsDataURL(file);
  }

  function analyzeQuaggaFile(src){
  Quagga.decodeSingle({
//    src: "/image-002.jpg",
    src: src,
    numOfWorkers: 0,  // Needs to be 0 when used within node
    inputStream: {
        size: 800  // restrict input-size to be 800px in width (long-side)
    },
    decoder: {
        readers: ["ean_reader"] // List of active readers
    },
  }, function(result) {
      if(result.codeResult) {
          console.log("result", result.codeResult.code);
          document.getElementById("quaggaIsbn").value = result.codeResult.code  ;
      } else {
          console.log("not detected");
      }
  });
}

  return (
    <Dialog open={open} onClose={onRequestClose}>
      <DialogTitle id="new-project-dialog-title">Sell book</DialogTitle>

      <Formik initialValues={{ name: '' }} onSubmit={handleSubmit}>
        {({ errors, isSubmitting }) => (
          <Form className={classes.root}>
            <DialogContent>
              <Field
                id="quaggaIsbn"
                name="isbn"
                label="ISBN"
                component={TextField}
                margin="normal"
                fullWidth
              />
              Scan bar code:<input id="quaggaFile" type="file" accept="image/*" capture="camera" onChange={inputFile}/>
              <Field
                name="title"
                label="Title"
                component={TextField}
                margin="normal"
                fullWidth
              />
              <Field
                name="status"
                label="Status"
                component={TextField}
                margin="normal"
                fullWidth
              />
              <Field
                name="price"
                label="Price"
                component={TextField}
                margin="normal"
                fullWidth
              />
              Book cover:<input id="image" type="file"/>
            </DialogContent>
            <DialogActions>
              <Button onClick={onRequestClose} color="secondary">
                Cancel
              </Button>
              <Button type="submit" color="primary" disabled={isSubmitting}>
                {isSubmitting ? 'Creating...' : 'Create'}
              </Button>
            </DialogActions>
          </Form>
        )}
      </Formik>


    </Dialog>
  )
}

NewProjectDialog.propTypes = {
  onSubmit: PropTypes.func.isRequired,
  open: PropTypes.bool.isRequired,
  onRequestClose: PropTypes.func.isRequired
}

export default NewProjectDialog

【问题讨论】:

  • 您想设置默认值还是应该何时更改该值?
  • 当我选择一个文件并加载到#quaggaFile 时,我想更改#quaggaIsbn 的值。 (它反映到视图而不是表单信息,当我提交表单时,它不会发送到服务器。)
  • 当我上传文件时,会调用 inputFile()。调用analyzeQuaggaFile() 和analyzeQuaggaFile() 尝试更改表单值#quaggaIsbn,但似乎没有因为#quaggaIsbn 的值未包含在提交的数据中。

标签: javascript reactjs redux material-ui formik


【解决方案1】:

一旦使用 enableReinitialize 属性在其上下文之外更新其属性,就可以重置整个 Formik。

https://formik.org/docs/api/formik#enablereinitialize-boolean

像这样:

<Formik validationSchema={validationSchema} initialValues={this.state.formValues} onSubmit={this.handleFormSubmission} enableReinitialize={true}>

【讨论】:

    【解决方案2】:

    Formik 渲染方法提供了一个使用 setFieldValue 手动更改字段值的道具,它将字段名称和新值作为参数,您可以从 here 了解更多信息

    至于你需要改变的是这里

    // accept a new parameter which you can pass to the `analyzeQuaggaFile` function
    function inputFile(setFieldValue) {
      const file = document.getElementById("quaggaFile").files[0];
    
      const reader = new FileReader();
    
      reader.addEventListener(
        "load",
        function () {
          // pass the setFieldValue
          analyzeQuaggaFile(reader.result, setFieldValue);
        },
        false
      );
    
      reader.readAsDataURL(file);
    }
    
    // second parameter is setFieldValue
    function analyzeQuaggaFile(src, setFieldValue) {
      Quagga.decodeSingle(
        {
          src: src,
          numOfWorkers: 0,
          inputStream: {
            size: 800,
          },
          decoder: {
            readers: ["ean_reader"],
          },
        },
        function (result) {
          if (result.codeResult) {
            // update the isbn field value
            setFieldValue("isbn", result.codeResult.code);
          } else {
            console.log("not detected");
          }
        }
      );
    }
    

    现在在你的 JSX 代码中改变这个:

    <Formik initialValues={{ name: "" }} onSubmit={handleSubmit}>
      {({ errors, isSubmitting, setFieldValue }) => (
        <Form className={classes.root}>
          {/* Other fields */}
          Scan bar code:
          <input
            id="quaggaFile"
            type="file"
            accept="image/*"
            capture="camera"
            onChange={() => inputFile(setFieldValue)} // pass the setFieldValue property from formik 
          />
          {/* Other fields */}
        </Form>
      )}
    </Formik>;
    

    【讨论】:

    • 太棒了!谢谢!!
    【解决方案3】:

        import {
          useFormik
        } from "formik";
        import * as yup from 'yup';
    
        export default function ChangeFormikValueOutsideForm() {
          const initialValues = {
            first_name: 'John',
            last_name: 'Doe'
          }
          const validationSchema = yup.object({
            first_name: yup.string("must be a string")
              .required("Must have a first name"),
            last_name: yup.string("must be a string")
          })
          const formik = useFormik({
              initialValues,
              validationSchema,
              onSubmit: (values) => {}
            )
          }
        }
    
        let handleLastNameChange = () => {
          formik.setFieldValue('last_name', Math.ceil(Math.random() * 100))
        }
    
        return (
        <form onSubmit = {
            formik.handleSubmit
          } >
          <p> First Name * </p> 
          <input
            name = "first_name"
            id = "first_name"
            type = "text"
            onChange = {
              formik.handleChange
            }
            value = {
              formik.values.first_name
            }
          />
          <p> Last Name </p>
          <input
            name = "last_name"
            id = "last_name"
            type = "text"
            onChange = {
              handleLastNameChange
            }
            value = {
              formik.values.last_name
            }
          />
          <input
            type = "submit"
            value = "Submit Form"
          />
          </form>
          )
        }

    它与 useFormik 钩子一起工作,这允许您在 formik 标记之外定义表单,然后从 formik 变量中受益,以在表单之外执行 setFieldValue 方法。事实上,您正在处理的表格完全脱离了表格;)

    与材质 ui 一起使用的想法也相同。它有效

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-13
      • 1970-01-01
      • 1970-01-01
      • 2020-05-21
      • 1970-01-01
      • 2021-04-28
      • 2022-11-15
      相关资源
      最近更新 更多