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

Ale*_*Dim 5 javascript reactjs next.js formik

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

我在处理什么:

  1. Express 上基于 API 的前端和后端分离(现在都在本地主机上)
  2. React (+ dom) 和 Next.js
  3. React 材质-UI
  4. 福米克

建筑学:

前端发送请求(基于表单输入) - >服务器接收它(使用它进行操作)并用json对象响应 - >前端接受它,并将结果显示回页面上。

  • 后端(启用正确的 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;
Run Code Online (Sandbox Code Playgroud)

服务器

  • 前端(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
Run Code Online (Sandbox Code Playgroud)

就目前而言,myForm 工作正常,通过提交表单从 API 接收到必要的数据。结果存储为res变量并在页面上显示为弹出窗口。

资源

但我想在页面上看到它。像这样:

资源

网络上没有太多教程来逐步介绍此过程。我知道在通过Next.js 获取的数据getInitialProps中。(但是没有表单提交的例子)

我将组件放置在页面上:

export default function Index() {
  return (
    <Container maxWidth="sm">
      <Box my={4}>
        <Form />
        <Here is an element with search form results />
      </Box>
    </Container>
  );
}
Run Code Online (Sandbox Code Playgroud)

然后我读到我无法将子组件的道具返回给父组件。或者我可以吗?我也无法将res变量作为组件值放置在表单内部或外部:

在此输入图像描述

那么我现在应该做什么呢?无论如何,我在教程中没有找到任何相关示例Formik。我知道它在某种程度上与state类似的操作有关componentDiDMount,这就是前端开发人员使用诸如Redux. 但有人可以解释一下我做错了什么吗?

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

根据@Shyam 的回答,我更新了我的代码。就目前而言,表单有以下代码:

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);
        }}
    ...
Run Code Online (Sandbox Code Playgroud)

index.js根据以下建议,

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

https://reacttricks.com/sharing-global-data-in-next-with-custom-app-and-usecontext-hook/

小智 2

一种方法是将回调函数作为 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>
  );
}
Run Code Online (Sandbox Code Playgroud)

在 MyForm 中,在控制台日志之后您可以调用props.myCallbackFunction(res).

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

希望这有帮助。