Форма Formik становится очень медленно набирать. Я узнал о FastField и что вся моя форма может быть перерисована, когда пользователь вводит данные в любое поле. Но я не уверен, как использовать FastField в моем коде.
Вот краткое описание того, что делает мой код. Есть 2 компонента; DailyLog.js
и Question.js
.
DailyLog.js
использует Formik, который содержит Form
курс. Form
отображает questionsList
. Это массив Question
компонентов. questionsList
создается из объекта questionsTemplate, который предоставляет такие свойства, как вопрос, описание и заполнитель для каждого вопроса. questionsList
is массив Question.js
дочерних компонентов, которым передан вопросObj, содержащий вышеупомянутые свойства. Question.js
содержит форму CustomField
. Я следил за этим обучающим видео formik 2 Беном Авадом, которого я нашел на странице ресурсов formik . Я использовал пользовательское поле formik CustomField
, чтобы вернуть материал-ui TextField
s. Question.js
renders answerType
, который описывает формат, в котором CustomField
s представлены для каждого вопроса. - Формат основан на
initialValues
структуре формы в DailyLog.js
. Если свойство intialValues является строкой, то answerType
будет просто CustomField
. Если это массив строк, то это будет FieldArray CustomFields
. Если это массив объектов, то в таблице будет отображаться FieldArray
из CusomtFields
.
Моя форма теперь работает очень медленно. Пожалуйста, посоветуйте, что мне делать, и если FastField является ответом. Вот код Я предоставил комментарии для вашей читабельности. Спасибо, Сурадж
<code>// DailyLog.js
import React from "react";
import { Formik, Form } from "formik";
import { Button } from "@material-ui/core";
import formInititalValues from "./formInitialValues";
import Question from "../components/FormElements/Question";
import questionsTemplate from "../components/DailyLog/questionsTemplate";
import "./DailyLog.css";
const DailyLog = () => {
const questionsList = Object.entries(questionsTemplate).map(
([property, questionObj], index) => {
return (
<Question
key={index}
id={property}
property={property}
questionObj={questionObj}
/>
);
}
);
return (
<main className="container">
<Formik
initialValues={formInititalValues}
onSubmit={(data, { setSubmitting }) => {
setSubmitting(true);
// TODO: make async call to db
console.log(data);
setSubmitting(false);
}}
>
{({ values, errors, isSubmitting }) => (
<Form>
<h1>Today's plan</h1>
{questionsList}
<div>
<Button disabled={isSubmitting} type="submit">
Submit
</Button>
</div>
<pre>{JSON.stringify(values, null, 2)}
)} ); }; экспорт по умолчанию DailyLog;
// questionsTemplate.js
module.exports = {
title: {
question: "Title",
description: "Day, date, calendar scheme",
placeholder: "Tuesday, 07.04.20, M4W2D4 ",
},
focus: {
question:
"What is this week's focus?",
description:
"Remember how much time is left for the weekly and monthly goals.",
placeholder: "This month's/week's focus is...",
},
// and so on...
}
// Question.js
import React from "react";
import { useField, FieldArray, useFormikContext } from "formik";
import {
TextField,
Button,
TableContainer,
Table,
TableHead,
TableRow,
TableCell,
TableBody,
} from "@material-ui/core";
import "./Question.css";
// create a custom formik textfield
const CustomField = ({ placeholder, ...props }) => {
const [field, meta] = useField(props);
return <TextField placeholder={placeholder} {...field} multiline />;
};
// The question component
const Question = ({ property, questionObj }) => {
const { values, setFieldValue } = useFormikContext();
// variable to store the format of input components returned i.e. simple textfield (if property value is string) or a list of input fields (if property value is array of strings) or a table of input fields (if property value is array of objects)
let answerType = "";
// variable to store the structure of a property item if property is an array of objects. It stores the structure (key:value) values as empty. Used for field reseting.
const answerInitialValue = {};
// if the forminitialvalue of property is of type string
if (typeof values[property] === "string") {
answerType = (
<CustomField name={property} placeholder={questionObj.placeholder} />
);
// if forminitialvalues property is not string but an array.
} else if (Array.isArray(values[property])) {
// if the array contains strings
if (typeof values[property][0] === "string") {
// return input fields for each item in the string
answerType = (
<FieldArray name={property}>
{arrayHelpers => {
return (
<div>
<Button onClick={() => arrayHelpers.push("")}>Add</Button>
{values[property].map((item, index) => (
<div key={index}>
<CustomField
placeholder={questionObj.placeholder}
name={`${property}.${index}`}
/>
{/* delete button deletes only if there is more than one item otherwise it only clears the field of the item thats left */}
<Button
onClick={() => {
values[property].length > 1
? arrayHelpers.remove(index)
: setFieldValue(`${property}.${index}`, "");
}}
>
x
</Button>
</div>
))}
</div>
);
}}
</FieldArray>
);
}
// if the array contains objects which are not arrays
else if (
typeof values[property][0] === "object" &&
!Array.isArray(values[property][0])
) {
// create an object of empty values so that it can be used to reset this answer field if required by a rest button.
for (const subProperty in values[property][0]) {
if ({}.hasOwnProperty.call(values[property][0], subProperty)) {
answerInitialValue[subProperty] = "";
}
}
// return input fields for each property in the object
answerType = (
<FieldArray name={property}>
{arrayHelpers => (
<div>
<Button onClick={() => arrayHelpers.push(answerInitialValue)}>
Add
</Button>
{/* creating a table format for properties that are array of objects */}
<TableContainer>
<Table size="small">
<TableHead>
<TableRow>
{Object.keys(values[property][0]).map((key, index) => (
<TableCell key={index}>{key}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{values[property].map((object, index) => {
return (
<TableRow key={index}>
{/* // rendering the fields for each property. example. start, end and log properties of logs parent property */}
{Object.keys(object).map((objKey, i) => (
<TableCell key={i}>
<CustomField
placeholder=""
name={`${property}.${index}.${objKey}`}
/>
</TableCell>
))}
<TableCell>
{/* delete button deletes only if there is more than one item otherwise it only clears the field of the item thats left */}
<Button
onClick={() => {
values[property].length > 1
? arrayHelpers.remove(index)
: setFieldValue(
`${property}.${index}`,
answerInitialValue
);
}}
>
x
</Button>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
</div>
)}
</FieldArray>
);
}
}
// render the question component and display the input fields format as stored in answerType
return (
<div className="form__group">
<label className="form__label">
<h2>{questionObj.question}</h2>
</label>
<small className="form__description">{questionObj.description}</small>
{answerType}
</div>
);
};
export default Question;
// formInitialValues
module.exports = {
title: "",
focus: [""],
todos: [""],
logs: [
{
start: "",
end: "",
log: "",
},
],
learnings: [
{
learning: "",
source: "",
},
],
thoughts: [""],
// and so on...
};