Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何使用formik 2和react表7呈现可编辑表?_Reactjs_React Hooks_Formik_React Table - Fatal编程技术网

Reactjs 如何使用formik 2和react表7呈现可编辑表?

Reactjs 如何使用formik 2和react表7呈现可编辑表?,reactjs,react-hooks,formik,react-table,Reactjs,React Hooks,Formik,React Table,我有这样一个场景,我从服务器加载表单的数据(比如一个包含用户好友列表的用户实体) 表单将具有可编辑名称的好友列表呈现为表7中的表。 我面临的问题是,每当我试图编辑此列表中朋友的姓名时,我只能键入一个字符,然后输入的内容就会失去焦点。我再次单击输入,键入1 char,它再次失去焦点 我创建了一个codesandbox来说明问题: 我理解为什么会发生这种情况——因为formik状态发生变化,所以每次我键入时表都会重新呈现——但我不确定如何防止这种情况发生。我useMemo-ed和useCallbac

我有这样一个场景,我从服务器加载表单的数据(比如一个包含用户好友列表的用户实体)

表单将具有可编辑名称的好友列表呈现为表7中的表。 我面临的问题是,每当我试图编辑此列表中朋友的姓名时,我只能键入一个字符,然后输入的内容就会失去焦点。我再次单击输入,键入1 char,它再次失去焦点

我创建了一个codesandbox来说明问题:

我理解为什么会发生这种情况——因为formik状态发生变化,所以每次我键入时表都会重新呈现——但我不确定如何防止这种情况发生。我
useMemo
-ed和
useCallback
-ed了我所能想到的一切(也
React.memo
-ed了组件,希望它能防止问题的发生),但到目前为止运气不好

如果我删除
好友
中的
useffect
,它确实会起作用,但是,这会使表在超时过期后不会更新(因此它在1s后不会显示2个好友)。
非常感谢您提供的任何帮助……我一整天都在解决这个问题。

哇,使用React附带的所有不同挂钩,您真的玩得很开心;-)我看了你的代码沙盒大概15分钟了。我的观点是,对于这样一项简单的任务来说,它的设计过于复杂。无意冒犯。我要做的是:

  • 试着退一步,从重构index.js开始简单操作,并按照Formik主页上的预期使用
    FieldArray
    (每个朋友一次渲染)
  • 下一步,您可以围绕它构建一个简单的表
  • 然后,您可以尝试使用输入字段编辑不同的字段
  • 如果您真的需要它,您可以添加
    react表
    库,但我认为没有它应该很容易实现
下面是一些代码,向您展示我的意思:

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { Formik, Form, FieldArray, Field } from "formik";
import Input from "./Input";
import "./styles.css";

const initialFormData = undefined;

function App() {
  const [formData, setFormData] = useState(initialFormData);

  useEffect(() => {
    // this is replacement for a network call that would load the data from a server
    setTimeout(() => {
      setFormData({
        id: 1,
        firstName: "First Name 1",
        friends: [
          { id: 2, firstName: "First Name 2", lastName: "Last Name 2" },
          { id: 3, firstName: "First Name 3", lastName: "Last Name 3" }
        ]
      });
    }, 1000);
    // Missing dependency array here
  }, []);

  return (
    <div className="app">
      {formData && (
        <Formik initialValues={formData} enableReinitialize>
          {({ values }) => (
            <Form>
              <Input name="name" label="Name: " />
              <FieldArray name="friends">
                {arrayHelpers => (
                  <div>
                    <button
                      onClick={() =>
                        arrayHelpers.push({
                          id: Math.floor(Math.random() * 100) / 10,
                          firstName: "",
                          lastName: ""
                        })
                      }
                    >
                      add
                    </button>
                    <table>
                      <thead>
                        <tr>
                          <th>ID</th>
                          <th>FirstName</th>
                          <th>LastName</th>
                          <th />
                        </tr>
                      </thead>
                      <tbody>
                        {values.friends && values.friends.length > 0 ? (
                          values.friends.map((friend, index) => (
                            <tr key={index}>
                              <td>{friend.id}</td>
                              <td>
                                <Input name={`friends[${index}].firstName`} />
                              </td>
                              <td>
                                <Input name={`friends[${index}].lastName`} />
                              </td>
                              <td>
                                <button
                                  onClick={() => arrayHelpers.remove(index)}
                                >
                                  remove
                                </button>
                              </td>
                            </tr>
                          ))
                        ) : (
                          <tr>
                            <td>no friends :(</td>
                          </tr>
                        )}
                      </tbody>
                    </table>
                  </div>
                )}
              </FieldArray>
            </Form>
          )}
        </Formik>
      )}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React,{useState,useffect}来自“React”;
从“react dom”导入react dom;
从“Formik”导入{Formik,Form,FieldArray,Field};
从“/Input”导入输入;
导入“/styles.css”;
const initialFormData=未定义;
函数App(){
const[formData,setFormData]=使用状态(initialFormData);
useffect(()=>{
//这是对从服务器加载数据的网络调用的替换
设置超时(()=>{
setFormData({
id:1,
名字:“名字1”,
朋友们:[
{id:2,firstName:“firstName 2”,lastName:“lastName 2”},
{id:3,firstName:“firstName 3”,lastName:“lastName 3”}
]
});
}, 1000);
//此处缺少依赖项数组
}, []);
返回(
{formData&&(
{({values})=>(
{arrayHelpers=>(
arrayHelpers.push({
id:Math.floor(Math.random()*100)/10,
名字:“,
姓氏:“
})
}
>
添加
身份证件
名字
姓氏
{values.friends&&values.friends.length>0(
values.friends.map((friends,index)=>(
{friend.id}
arrayHelpers.remove(索引)}
>
去除
))
) : (
没有朋友:(
)}
)}
)}
)}
);
}
const rootElement=document.getElementById(“根”);
render(,rootElement);
现在,一切都是一个组件。如果您愿意,您现在可以将其重构为不同的组件,或者检查您可以应用哪种类型的挂钩;-)从简单开始,让它工作起来。然后你可以继续剩下的

更新

更新好友组件时,如下所示:

import React, { useCallback, useMemo } from "react";
import { useFormikContext, getIn } from "formik";
import Table from "./Table";
import Input from "./Input";

const EMPTY_ARR = [];

function Friends({ name, handleAdd, handleRemove }) {
  const { values } = useFormikContext();

  // from all the form values we only need the "friends" part.
  // we use getIn and not values[name] for the case when name is a path like `social.facebook`
  const formikSlice = getIn(values, name) || EMPTY_ARR;

  const onAdd = useCallback(() => {
    const item = {
      id: Math.floor(Math.random() * 100) / 10,
      firstName: "",
      lastName: ""
    };
    handleAdd(item);
  }, [handleAdd]);

  const onRemove = useCallback(
    index => {
      handleRemove(index);
    },
    [handleRemove]
  );

  const columns = useMemo(
    () => [
      {
        Header: "Id",
        accessor: "id"
      },
      {
        Header: "First Name",
        id: "firstName",
        Cell: ({ row: { index } }) => (
          <Input name={`${name}[${index}].firstName`} />
        )
      },
      {
        Header: "Last Name",
        id: "lastName",
        Cell: ({ row: { index } }) => (
          <Input name={`${name}[${index}].lastName`} />
        )
      },
      {
        Header: "Actions",
        id: "actions",
        Cell: ({ row: { index } }) => (
          <button type="button" onClick={() => onRemove(index)}>
            delete
          </button>
        )
      }
    ],
    [name, onRemove]
  );

  return (
    <div className="field">
      <div>
        Friends:{" "}
        <button type="button" onClick={onAdd}>
          add
        </button>
      </div>
      <Table data={formikSlice} columns={columns} rowKey="id" />
    </div>
  );
}

export default React.memo(Friends);
import React,{useCallback,UseMoom}来自“React”;
从“formik”导入{useFormikContext,getIn};
从“/Table”导入表;
从“/Input”导入输入;
常量空_ARR=[];
函数好友({name,handledd,handleRemove}){
常量{values}=useFormikContext();
//从所有表单值中,我们只需要“朋友”部分。
//当名称是类似“social.facebook”的路径时,我们使用getIn而不是值[name]`
const formikSlice=getIn(值、名称)| | EMPTY_ARR;
const onAdd=useCallback(()=>{
常数项={
id:Math.floor(Math.random()*100)/10,
名字:“,
姓氏:“
};
手持(项目);
},[handleAdd]);
const onRemove=useCallback(
索引=>{
handleRemove(索引);
},
[handleRemove]
);
const columns=useMoom(
() => [
{
标题:“Id”,
访问者:“id”
},
{
标题:“名字”,
id:“名字”,
单元格:({row:{index}})=>(
)
},
{
标题:“姓氏”,
id:“姓氏”,
单元格:({