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