Я не могу предварительно заполнить поля ввода в моей форме. Может кто-нибудь мне помочь?

Я только начал изучать MERN и создал простое приложение, в котором мне нужно добавлять элементы в меню, обновлять и удалять их. для обновления я хочу предварительно заполнить поле ввода данными элемента.

Я сижу над этой проблемой уже много времени, но не могу найти решение. Я установил атрибут значения для каждого ввода, но все равно не вижу никакой информации в поле ввода.

Реагировать на код

MenuItems.jsx

import React, { useEffect, useState } from "react";
import edit from "/edit.png";
import rupee from "../utils/currencyFormatter.jsx";
import api from "../api/api.jsx";
import { capitalize } from "../utils/capitalize.jsx";
import available from "/available.png";
import notavailable from "/notavailable.png";
import deleteImg from "/delete.png";
import EditItem from "./editItem.jsx";

const menuItems = ({ category }) => {
    const [editForm, setEditForm] = useState(false);
    const [items, setItems] = useState([]);
    useEffect(() => {
        const getItems = async () => {
            try {
                const response = await api.get("/menu");
                setItems(response.data);
            } catch (error) {
                console.info(error.message);
            }
        };
        getItems();
    }, []);
    const [idi, setId] = useState(0);
    return (
        <ol>
            {editForm && (
                <EditItem
                    isVisible = {editForm}
                    setIsVisible = {setEditForm}
                    category = {category}
                    id = {idi}
                />
            )}
            {items.map((i, index) => (
                <li
                    key = {i._id}
                    className = "grid grid-cols-6 text-[1.5vw] p-3 transition-all duration-100 hover:bg-orange-400 rounded-md"
                >
                    {index + 1}
                    <p className = " flex flex-col justify-center font-semibold">
                        {capitalize(i.item)}
                        <span className = "font-thin text-[1.3vw]">
                            {i.description}
                        </span>
                    </p>
                    <span>{rupee.format(i.price)}</span>
                    <span>
                        {i.availability ? (
                            <img
                                src = {available}
                                alt = "Available"
                                className = " h-8 w-8"
                            />
                        ) : (
                            <img
                                src = {notavailable}
                                alt = "Not Available"
                                className = " h-8 w-8"
                            />
                        )}
                    </span>
                    <button
                        onClick = {() => {
                            setEditForm(true);
                            setId(i._id);
                        }}
                    >
                        <img src = {edit} alt = "edit" className = "h-10 w-10" />
                    </button>
                    <button>
                        <img
                            src = {deleteImg}
                            alt = "delete"
                            className = " h-10 w-10"
                        />
                    </button>
                </li>
            ))}
        </ol>
    );
};

export default menuItems;

EditItem.jsx

import React, { useEffect, useRef, useState } from "react";
import axios from "../api/api.jsx";

const editItem = ({ isVisible, setIsVisible, category, id }) => {
    const [formData, setFormData] = useState({});
    useEffect(() => {
        const getItems = async () => {
            try {
                const response = await axios.get(`/menu/${id}`);
                setFormData(response.data);
                
                console.info("updated formData:", formData);
            } catch (error) {
                console.info(error.message);
                setFormData({});
            }
        };
        getItems();
    }, [id]);
    const handleSubmit = async (event) => {
        event.preventDefault();
        try {
            console.info(formData.category);
            const response = await axios.put(`/menu/${id}`, formData);
            console.info(response.data);
        } catch (error) {
            console.error(error.message);
        }
        setIsVisible(!isVisible);
    };
    if (!isVisible) return null;
    return (
        <div className = "fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex justify-center items-center">
            <div className = "w-[50%] flex flex-col">
                <div className = "bg-white p-2 rounded">
                    <h2 className = "mb-4 text-2xl text-center font-bold text-gray-900">
                        Add a new product
                    </h2>
                    <form
                        action = "post"
                        className = " p-4"
                        onSubmit = {handleSubmit}
                    >
                        <div className = "grid gap-4 sm:grid-cols-2 sm:gap-6">
                            <div className = "sm:col-span-2">
                                <label
                                    htmlFor = "item"
                                    className = "block mb-2 text-sm font-medium text-gray-90"
                                >
                                    Item Name
                                </label>
                                <input
                                    type = "text"
                                    name = "item"
                                    id = "item"
                                    className = "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 "
                                    placeholder = "Type Item name"
                                    required
                                    value = {formData.item}
                                    onChange = {(event) => {
                                        setFormData({
                                            ...formData,
                                            item: event.target.value,
                                        });
                                        console.info(
                                            "Item input value:",
                                            event.target.value
                                        );
                                    }}
                                />
                            </div>
                            <div className = "w-full">
                                <label
                                    htmlFor = "price"
                                    className = "block mb-2 text-sm font-medium text-gray-90"
                                >
                                    Price
                                </label>
                                <input
                                    type = "number"
                                    name = "price"
                                    id = "price"
                                    className = "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 "
                                    required
                                    placeholder = "Add the price"
                                    value = {formData.price}
                                    onChange = {(event) =>
                                        setFormData({
                                            ...formData,
                                            price: event.target.value,
                                        })
                                    }
                                />
                            </div>
                            <div>
                                <label
                                    htmlFor = "category"
                                    className = "block mb-2 text-sm font-medium text-gray-90"
                                >
                                    Category
                                </label>
                                <select
                                    id = "category"
                                    className = "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 "
                                    value = {formData.category}
                                    onChange = {(event) => {
                                        setFormData({
                                            ...formData,
                                            category: event.target.value,
                                        });
                                    }}
                                >
                                    <option>Select category</option>
                                    {category.map((c) => (
                                        <option key = {c._id} value = {c._id}>
                                            {c.name}
                                        </option>
                                    ))}
                                </select>
                            </div>
                            <div className = "flex items-center">
                                <label
                                    htmlFor = "availability"
                                    className = "block mb-2 text-sm font-medium text-gray-90 mr-5"
                                >
                                    Availability
                                </label>
                                <input
                                    type = "checkbox"
                                    name = "avaialability"
                                    id = "availability"
                                    value = {formData.availability}
                                    onChange = {(event) => {
                                        if (event.target.checked) {
                                            setFormData({
                                                ...formData,
                                                availability: true,
                                            });
                                        }
                                    }}
                                />
                            </div>
                            <div className = "flex gap-4 items-center">
                                <label
                                    htmlFor = "veg"
                                    className = "block mb-2 text-sm font-medium text-gray-90"
                                >
                                    Veg
                                </label>
                                <input
                                    type = "radio"
                                    name = "veg_or_nonveg"
                                    value = "veg"
                                    id = "veg"
                                    onChange = {(event) =>
                                        setFormData({
                                            ...formData,
                                            veg_or_nonveg: event.target.value,
                                        })
                                    }
                                />
                                <label
                                    htmlFor = "nonveg"
                                    className = "block mb-2 text-sm font-medium text-gray-90"
                                >
                                    Non Veg
                                </label>
                                <input
                                    type = "radio"
                                    name = "veg_or_nonveg"
                                    value = "non-veg"
                                    id = "nonveg"
                                    onChange = {(event) =>
                                        setFormData({
                                            ...formData,
                                            veg_or_nonveg: event.target.value,
                                        })
                                    }
                                />
                            </div>
                            <div className = "sm:col-span-2">
                                <label
                                    htmlFor = "description"
                                    className = "block mb-2 text-sm font-medium text-gray-90"
                                >
                                    Description
                                </label>
                                <textarea
                                    id = "description"
                                    rows = "8"
                                    className = "block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-primary-500 focus:border-primary-500 "
                                    placeholder = "Item Description"
                                    value = {formData.description}
                                    onChange = {(event) =>
                                        setFormData({
                                            ...formData,
                                            description: event.target.value,
                                        })
                                    }
                                ></textarea>
                            </div>
                        </div>
                        <div className = "flex">
                            <button
                                type = "submit"
                                className = "flex items-center px-5 py-2.5 mt-2 text-sm font-medium text-center rounded-lg focus:ring-4 focus:ring-primary-200"
                            >
                                Edit product
                            </button>
                            <button
                                className = " flex items-center px-5 py-2.5 mt-2 text-sm font-medium text-center rounded-lg text-red-600  focus:ring-4 focus:ring-primary-200"
                                onClick = {() => {
                                    setIsVisible(!isVisible);
                                }}
                            >
                                Cancel
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    );
};

export default editItem;

Экспресс-код

контролеры

import mongoose from "mongoose";
import { menuModel } from "../models/menuModel.js";

export const getMenuItems = async (req, res) => {
    try {
        const menuItems = await menuModel.find();
        res.status(200).json(menuItems);
    } catch (err) {
        res.status(404).json({ message: err.message });
        console.info(err);
    }
};

export const getOneItem = async (req, res) => {
    const id = req.params.id;
    try {
        const item = await menuModel.find({ _id: id });
        res.status(200).json(item);
    } catch (err) {
        res.status(404).json({ message: err.message });
    }
};

export const addMenuItems = async (req, res) => {
    const item = req.body;
    const newItem = new menuModel(item);
    try {
        await newItem.save();
        res.status(201).json(newItem);
        console.info(newItem);
    } catch (err) {
        console.info(err);
        res.status(409).json({ message: err.message });
    }
};

export const updateMenuItmes = async (req, res) => {
    const { id: _id } = req.params;
    const updatedData = req.body;
    try {
        if (!mongoose.Types.ObjectId.isValid(_id))
            return res.status(404).send("no item with that id exists");
        const updates = await menuModel.findByIdAndUpdate(_id, updatedData, {
            new: true,
        });
        res.status(200).json(updates);
    } catch (err) {
        res.status(409).json({ message: err.message });
    }
};

// export const deleteItems = async (req,res) =>{
// }

MenuModel.jsx — содержит модель меню.

import { Decimal128 } from "mongodb";
import mongoose, { model } from "mongoose";
const { Schema } = mongoose;

const menuSchema = new Schema({
    item: {
        type: String,
        required: true,
        unique: true,
    },
    price: {
        type: Number,
        required: true,
        default: 0.0,
    },
    availability: {
        type: Boolean,
        required: true,
        default: true,
    },
    veg_or_nonveg: {
        type: String,
        required: true,
        enum: ["Veg", "Non-Veg", "veg", "non-veg"],
    },
    description: {
        type: String,
    },
    category: [
        {
            type: Schema.Types.ObjectId,
            ref: "categoryModel",
        },
    ],
});

export const menuModel = new model('menuModel', menuSchema);

у меня есть добавленный атрибут значения, как вы можете видеть здесь, но я не нашел предварительно заполненных данных Может ли кто-нибудь помочь мне с этой проблемой.

вот репозиторий GitHub ссылка:

🤔 А знаете ли вы, что...
JavaScript был первоначально создан для улучшения интерактивности веб-страниц.


54
1

Ответ:

Решено

Похоже, у вас есть вызов getItems() в компоненте editItem, поэтому он снова извлекает те же данные, которые у вас уже были при отображении без редактирования - при условии, что /menu возвращает те же данные для всех элементов, что и /menu/id для одного. Задержка может возникнуть из-за ожидания ответа от базы данных.

Попробуйте передать значения в качестве реквизита компоненту редактирования, чтобы не получать его дважды. Если у вас есть несколько пунктов меню, вы можете сопоставить массив и передать реквизиты каждому отдельному компоненту элемента. а вы пробовали использовать defaultValue вместо значения для заполнения полей ввода?