简体   繁体   English

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

[英]How to return API (fetched) data from Formik Submit in Next.js

I'm new @frontend and found it a bit challenging creating a simple search form in Next.js with using Formik and return data fetched from my own API back on page. 我是新来的@frontend,发现使用FormikNext.js创建一个简单的搜索表单并返回从我自己的API提取的数据返回页面有点挑战。 As there are not so much relevant information about, or there is, but it doesn't cover the whole process, so I decided to create this question. 由于没有或没有足够的相关信息,但是它没有涵盖整个过程,所以我决定提出这个问题。

What am I dealing with: 我要处理的是:

  1. separated front-end and back-end based API on express (both on localhost right now) 在Express上分离了基于前端和后端的API(现在都在localhost上)
  2. React (+ dom) & Next.js React(+ dom)和Next.js
  3. React Material-UI React Material-UI
  4. Formik Formik

Architecture: 建筑:

Front send request (based on form input) -> Server received it (operates with it) and respond with json object -> Front takes it, and shows result back on page. 前端发送请求(基于表单输入)->服务器接收到该请求(对其进行操作)并以json对象响应->前端接收该请求,并在页面上显示结果。

  • Backend (correct CORS enabled) 后端(启用了正确的CORS)

A simple node.js express server with one-route (localhost:port/users/:id) when you request it like ./users/100 it returns json with {id}+1 increment, like {id:101} , example code below: 当您像./users/100这样的请求时,具有单路由(localhost:port / users /:id)的简单node.js快速服务器,它以{id} +1增量返回json ,例如{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;

服务器

  • Frontend (next.js + formik) 前端(next.js + formik)

I have already write MyForm component and insert it on my Home page. 我已经编写了MyForm组件并将其插入到我的主页中。 Here is a code of MyForm component: 这是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

As for now, myForm works fine, necessary data received from API via submitting form. 到目前为止,myForm可以正常工作,并且可以通过提交表单从API接收必要的数据。 The result is stored as res variable and showed as a popup on the page. 结果存储为res变量,并在页面上显示为弹出窗口。

水库

But I want to see it, back on page. 但我想在页面上看到它。 Like this: 像这样:

水库

There are not so much tutorials in the web that cover this process step-by-step. 网络上没有太多的教程逐步介绍此过程。 I know that in Next.js fetched data received via getInitialProps . 我知道在Next.js 获取了通过getInitialProps 接收到的数据 (But there are no examples with form submitting) (但没有表单提交的示例)

I place my component on page: 我将组件放在页面上:

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

And then I read that I can't return props from child component back to parent. 然后我读到我无法将道具从子组件退还给父组件 Or can I? 可以吗 I also can't place res variable as a component value inside or outside my form: 我也不能将res变量作为组件值放置在表单的内部或外部:

在此处输入图片说明

So what I should do now? 那我现在该怎么办? Anyway I haven't find any relevant example in Formik tutorial. 无论如何,我在Formik教程中找不到任何相关示例。 I understand that it is somehow connected with state manipulation like componentDiDMount and that's why frontend devs using modules like Redux . 我了解到它以某种方式与诸如componentDiDMount之类的state操纵相关联,这就是为什么前端开发人员使用Redux模块的原因。 But can someone explain me, what am I doing wrong? 但是有人可以向我解释,我在做什么错?

Also, if you have any relevant information and want to give me some advice or share it (like Formik is useless in this case, you should use X instead) don't be shy, just post it. 另外,如果您有任何相关信息并希望给我一些建议或分享(例如,Formik在这种情况下是无用的,则应使用X ),不要害羞,只需将其发布即可。 I'll check it out and upvote. 我会检查出来并支持。

According to @Shyam answer I updated my code. 根据@Shyam答案,我更新了代码。 As for now, form has the following code: 到目前为止,表单具有以下代码:

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);
        }}
    ...

and index.js according the below recommendation, index.js根据以下建议,

In this case React return me an error, connected with props but the form submission works fine. 在这种情况下, React我返回了一个错误,与props但是表单提交工作正常。 Guess I could found relevant information here: 猜猜我可以在这里找到相关信息:

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

One way would be to send a callback function to MyForm as a prop and have it called with res after the fetched result is received. 一种方法是将回调函数作为道具发送给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>
  );
}

Inside MyForm, after the console log you call props.myCallbackFunction(res) . 在MyForm内部,在控制台日志之后,您调用props.myCallbackFunction(res)

The best way would be to decouple the api call and the frontend logic and using some state management for loading, error, called states. 最好的方法是将api调用与前端逻辑解耦,并使用某种状态管理来加载,错误(称为状态)。 Ideally you should'nt be using setTimeouts in such scenarios. 理想情况下,您不应在这种情况下使用setTimeouts。

Hope this helped. 希望这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM