Javascript 如何在Next.js中从Formik Submit返回API(获取的)数据

Javascript 如何在Next.js中从Formik Submit返回API(获取的)数据,javascript,reactjs,next.js,formik,Javascript,Reactjs,Next.js,Formik,我是新来的@frontend,发现在Next.js中使用Formik创建一个简单的搜索表单并将从我自己的API获取的数据返回页面有点困难。因为没有太多相关的信息,或者说有,但是它没有涵盖整个过程,所以我决定提出这个问题 我在处理什么: 基于express的独立前端和后端API(都在 本地主机(现在) React(+dom)和Next.js 反应材料界面 福米克 架构: 前端发送请求(基于表单输入)->服务器接收到它(使用它进行操作),并使用jsonobject->前端接收它,并在页面上显示结果

我是新来的@frontend,发现在
Next.js
中使用
Formik
创建一个简单的搜索表单并将从我自己的API获取的数据返回页面有点困难。因为没有太多相关的信息,或者说有,但是它没有涵盖整个过程,所以我决定提出这个问题

我在处理什么:

  • 基于express的独立前端和后端API(都在 本地主机(现在)
  • React(+dom)和Next.js
  • 反应材料界面
  • 福米克
  • 架构:

    前端发送请求(基于表单输入)->服务器接收到它(使用它进行操作),并使用
    json
    object->前端接收它,并在页面上显示结果

    • 后端(已启用正确的CORS)
    一个简单的node.js express服务器,只有一条路由(localhost:port/users/:id),当您像
    /users/100
    那样请求它时,它返回
    json
    ,增量为{id}+1,像
    {id:101}
    ,示例代码如下:

    var express = require('express');
    var router = express.Router();
    
    /* CORS ARE FINE */
    router.get('/:id', function(req, res) {
      res.json({id: parseInt(req.params.id)+1});
    });
    
    module.exports = router;
    

    • 前端(next.js+formik)
    我已经编写了
    MyForm
    组件并将其插入我的主页。以下是
    MyForm
    组件的代码:

    import React from 'react';
    import fetch from 'isomorphic-unfetch'
    import { Formik, Form, Field } from 'formik';
    import { TextField } from 'formik-material-ui';
    import Button from "@material-ui/core/Button";
    
    const MyForm = () => (
        <Formik
            initialValues={{ text: '', password: '' }}
            onSubmit={ async (values, { setSubmitting }) => {
                const res = await fetch(`http://localhost:8000/users/${values.text}`, {
                    method: 'GET',
                    mode: 'cors',
                    headers: {
                        'Content-Type': 'application/json',
                        'Access-Control-Allow-Origin': '*'
                    }}).then(response => response.json());
                console.log(res);
                //props = res;
                //return props;
                setTimeout(() => {
                    alert(JSON.stringify(res, null, 2));
                    setSubmitting(false);
                }, 400);
            }}
        >
            {({ isSubmitting }) => (
                <Form>
                    <Field
                        name="text"
                        label="Text"
                        type="text"
                        variant="outlined"
                        component={TextField}
                    />
                    <Button
                        type="submit"
                        variant="contained"
                        color="primary"
                        disabled={isSubmitting}
                    >
                        Submit
                    </Button>
                </Form>
            )}
        </Formik>
    );
    
    export default MyForm
    
    然后回到父母身边。或者我可以吗?我也不能将
    res
    变量作为表单内外的组件值:

    那我现在该怎么办?无论如何,我在
    Formik
    教程中没有找到任何相关的例子。我知道它在某种程度上与
    状态
    操作(如
    componentDiDMount
    )有关,这就是前端开发人员使用
    Redux
    等模块的原因。但有人能解释一下,我做错了什么

    另外,如果你有任何相关信息,想给我一些建议或分享(比如在这种情况下Formik是无用的,你应该使用
    X
    ),不要害羞,只需发布即可。我会检查一下并投票表决

    根据@Shyam-answer,我更新了我的代码。目前,表单的代码如下:

    constmyform=(道具)=>(
    ...
    onSubmit={async(值,{setSubmitting})=>{
    const res=等待取数(`http://localhost:8000/users/${values.text}`{
    方法:“GET”,
    模式:“cors”,
    标题:{
    “内容类型”:“应用程序/json”,
    “访问控制允许来源”:“*”
    }}).then(response=>response.json());
    控制台日志(res);
    设置提交(假);
    props.myCallbackFunction(res);
    }}
    ...
    
    index.js
    根据以下建议

    在这种情况下,
    React
    返回一个与
    props
    相关的错误,但是表单提交工作正常。我想我可以在这里找到相关信息:


    一种方法是将回调函数作为prop发送到MyForm,并在收到获取的结果后使用res调用它

    export default function Index() {
      const [result, setResult] = useState(null)
      const callMeOnRes = (data) => {
         setResult(data)
      }
      return (
        <Container maxWidth="sm">
          <Box my={4}>
            <Form myCallbackFunction={(res) => callMeOnRes(res)} />
            {result && <div>{result}</div>}
            <Here is an element with search form results />
          </Box>
        </Container>
      );
    }
    
    导出默认函数索引(){
    const[result,setResult]=useState(null)
    const callMeOnRes=(数据)=>{
    设置结果(数据)
    }
    返回(
    callMeOnRes(res)}/>
    {result&&{result}
    );
    }
    
    在MyForm内部,在控制台日志之后调用
    props.myCallbackFunction(res)

    最好的方法是将api调用和前端逻辑解耦,并对加载、错误、调用状态使用一些状态管理。理想情况下,在这种情况下不应使用设置超时


    希望这能有所帮助。

    谢谢,我现在就去看看。至于带有
    setTimeout
    alert
    框(仅适用于我),只是为了确保API的结果返回并以
    类人的形式正确显示。我不会在我的最终项目中使用此模式。
    const[result,setResult]=useState(null)
    useState在这种情况下?我应该从某处导入它吗?useState来自react。您可以像
    react.useState
    一样使用它,或者在顶部使用常规导入。
    import react,{useState}从React
    并使用它。当这个状态被更新时,会再次调用完整的函数,这会导致result.y的更新。我在谷歌上搜索到,它似乎来自新创建的
    React Hooks
    ,因为现在我在
    props.myCallbackFunction(res)上有错误;
    它说
    道具没有定义
    。但是表单可以很好地工作。那么我应该如何正确地定义它们呢?//在我问题的最后,我刚刚更新了关于
    道具
    的信息。它现在应该在
    我的表单
    中使用
    (道具)
    const MyForm = (props) => (
        <Formik>
        ...
                onSubmit={ async (values, { setSubmitting }) => {
                const res = await fetch(`http://localhost:8000/users/${values.text}`, {
                    method: 'GET',
                    mode: 'cors',
                    headers: {
                        'Content-Type': 'application/json',
                        'Access-Control-Allow-Origin': '*'
                    }}).then(response => response.json());
                console.log(res);
                setSubmitting(false);
                props.myCallbackFunction(res);
            }}
        ...
    
    export default function Index() {
      const [result, setResult] = useState(null)
      const callMeOnRes = (data) => {
         setResult(data)
      }
      return (
        <Container maxWidth="sm">
          <Box my={4}>
            <Form myCallbackFunction={(res) => callMeOnRes(res)} />
            {result && <div>{result}</div>}
            <Here is an element with search form results />
          </Box>
        </Container>
      );
    }