Формик очень медленный. Как вы можете добавить <FastField>к пользовательскому полю, которое использует компонент material-ui? - PullRequest
0 голосов
/ 13 апреля 2020

Форма Formik становится очень медленно набирать. Я узнал о FastField и что вся моя форма может быть перерисована, когда пользователь вводит данные в любое поле. Но я не уверен, как использовать FastField в моем коде.

Вот краткое описание того, что делает мой код. Есть 2 компонента; DailyLog.js и Question.js.

  1. DailyLog.js использует Formik, который содержит Form курс.
  2. Form отображает questionsList. Это массив Question компонентов.
  3. questionsList создается из объекта questionsTemplate, который предоставляет такие свойства, как вопрос, описание и заполнитель для каждого вопроса.
  4. questionsList is массив Question.js дочерних компонентов, которым передан вопросObj, содержащий вышеупомянутые свойства.
  5. Question.js содержит форму CustomField. Я следил за этим обучающим видео formik 2 Беном Авадом, которого я нашел на странице ресурсов formik . Я использовал пользовательское поле formik CustomField, чтобы вернуть материал-ui TextField s.
  6. Question.js renders answerType, который описывает формат, в котором CustomField s представлены для каждого вопроса.
  7. Формат основан на 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...
};

...