Dan*_*gea 5 reactjs react-table formik react-hooks
我有一个场景,我从服务器加载表单数据(假设一个用户实体与用户的朋友列表)。
该表单将具有可编辑姓名的朋友列表呈现为带有 react-table 7 的表格。我面临的问题是,每当我尝试编辑此列表中朋友的姓名时,我只能输入一个字符,然后输入失去焦点。我再次单击输入,输入 1 个字符,它再次失去焦点。
我创建了一个codesandbox来说明问题:https ://codesandbox.io/s/formik-react-table-hr1l4
我理解为什么会发生这种情况 - 每次我输入时表格都会重新呈现,因为 formik 状态发生了变化 - 但我不确定如何防止这种情况发生。我useMemo-ed 和useCallback-ed 所有我能想到的(也React.memo-ed 组件,希望它能防止问题),但到目前为止还没有运气。
但是,如果我删除useEffectin Friends,它确实有效,这将使表在超时到期后不更新(因此它不会在 1 秒后显示 2 个朋友)。非常感谢任何帮助......我一整天都被困在这个问题上。
哇,你使用 React 附带的所有不同的钩子真的很有趣 ;-) 我看了你的代码和盒子大约 15 分钟了。我的观点是,对于这样一个简单的任务,它的设计过于复杂。没有恶意。我会怎么做:
FieldArray预期使用Formik 主页上的预期(每个朋友一个渲染)来开始简单。react-table库,但我认为没有它应该很容易实现它下面是一些代码来向你展示我的意思:
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);
Run Code Online (Sandbox Code Playgroud)
现在一切都是一个组件。如果您愿意,现在可以将其重构为不同的组件,或者检查您可以应用哪种钩子 ;-) 从简单开始并使其工作。然后你可以继续剩下的。
更新:
当您像这样更新 Friends 组件时:
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);
Run Code Online (Sandbox Code Playgroud)
它似乎不再散焦了。你也可以检查一下吗?我删除了 useEffect 块,该表直接与formikSlice. 我想问题在于,当您更改 Formik 值更新的输入时,会触发 useEffect 块以更新 Friends 组件的内部状态,从而导致表重新呈现。
| 归档时间: |
|
| 查看次数: |
3990 次 |
| 最近记录: |