Реагировать, не устанавливая состояние из выборки данных

У меня есть фрагмент JS-кода, который должен извлекать данные из конечной точки и заполнять форму из данных.

Основная проблема, с которой я столкнулся, заключается в том, что он заполняет только первое поле. Остальное не заполняет.

Компонент реакции показан ниже.

import React, { useState, useCallback, useEffect } from "react";
import {  Page, Button, Stack, Card, Form, FormLayout, TextField, TextContainer, Modal, Toast, TextStyle, Loading } from "@shopify/polaris";
import axiosInstance from "../common/RequestHandler";
import { useParams } from 'react-router-dom';
import { useNavigate } from "react-router";

function EditPackages(){
    const [errorToastActive, setErrorToastActive] = useState(false);

    const [active, setActive] = useState(false);
    const [isLoading, setIsLoading] = useState(false);

    const [height, setHeight] = useState('');
    const [width, setWidth] = useState('');
    const [depth, setDepth] = useState('');
    const [maxWeight, setMaxWeight] = useState('');
    const [packageName, setPackageName] = useState('');
    const [packageId, setPackageId] = useState(null);
    const [btnLoadingState, setBtnLoadingState] = useState(false);

    const [btnLoadingState, setBtnLoadingState] = useState(false);

    const toggleErrorToastActive = useCallback(() => setErrorToastActive((errorToastActive) => !errorToastActive), []);

    const errorToastMarkUp = errorToastActive ? (
        <Toast content = "Error in editing your package" error onDismiss = {toggleErrorToastActive} />
    ) : null;


    const params = useParams();
    const editPackageId = params.editPackageId;

    console.info("Edit Package ID -> ", editPackageId);

    const navigate = useNavigate();

    useEffect(async () => {
        const data = await retrievePackage();
        console.info(data);
        setMaxWeight(data.maxWeight);
        setDepth(data.depth);
        setHeight(data.height);
        setWidth(data.width);
        setPackageName(data.packageName);
    }, [editPackageId]);

    const backToPackages = function (){
        navigate('/app/packages');
    }

    const getPackage = useCallback(async () => {
        setPackageInfo(await retrievePackage());
    }, []);

    async function retrievePackage(){
        setIsLoading(true);
        const resp1 = await axiosInstance.get('/packageInfo?packageId=' + editPackageId);
        setIsLoading(false);
        return await resp1.data;
    }
    
    return (
        <Page title = "Edit Package" fullWidth>
            {errorToastMarkUp}
            <Form>
                <FormLayout>
                    <TextField label = "Package Name" value = {packageName} onChange = {setPackageName} autoComplete = "off" />
                <TextField label = "Height in CM" value = {height} onChange = {setHeight} autoComplete = "off" />
                <TextField label = "Width in CM"  value = {width} onChange = {setWidth} autoComplete = "off" />
                <TextField label = "Depth in CM"  value = {depth} onChange = {setDepth} autoComplete = "off" />
                <TextField label = "Max Weight in Grams"  value = {maxWeight} onChange = {setMaxWeight} autoComplete = "off" />
                    <Button submit>Submit</Button>
                </FormLayout>
            </Form>
        </Page>
    );
}

export default EditPackages;

Метод getPackage предназначен для извлечения данных из конечной точки, и я ожидаю, что setPackageInfo установит состояние/значения для объекта.

Я могу подтвердить, что данные API получены, и, чтобы еще больше меня запутать, текстовое поле заполняется packageInfo.packageName. Но в остальном ни одного. Я уверен, что имена также совпадают с извлечением данных.

Для лучшего понимания ниже мой ответ от конечной точки.

{
    "id": 25,
    "mId": 1,
    "height": 123,
    "width": 35,
    "depth": 3,
    "maxWeight": 4566,
    "created_at": "2022-02-18T21:13:47.000000Z",
    "updated_at": "2022-02-18T21:13:47.000000Z",
    "packageName": "Some random name"
}

Любая помощь очень ценится. Я несколько дней бился головой о кирпичную стену с этой проблемой. Заранее спасибо.

Не могли бы вы смоделировать проблему в JSFiddle или в песочнице кода, чтобы мы могли решить ее непосредственно там.

Asutosh 19.03.2022 06:46

Вы имеете в виду, что форма отображает ввод только с полем имени пакета, но не с другими?

sid 19.03.2022 06:47

Да правильно @sid

Ela Buwa 19.03.2022 10:30
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваш метод onChange неверен, поэтому вы получаете объект в ответе от axios, но как только один из onChange(s) запускается, состояние изменяется, и у вас остается только первое поле в дереве, а другие значения становятся нулевыми /неопределенный. Попробуйте изменить метод onChange на -
e=> setPackageInfo({...packageInfo, packageName: e.target.value}) для packageName,
e=> setPackageInfo({...packageInfo, height: e.target.value}) для высоты и так далее.

Спасибо. Я получаю «Uncaught TypeError: Невозможно прочитать свойства неопределенного (чтение« значения »)» при обновлении до onChange = {e => setPackageInfo({...packageInfo, packageName: e.target.value})}. Есть идеи? Это происходит, когда я печатаю в текстовом поле. Исходная проблема с заполнением поля packageName только после использования предложенного вами useEffect. Ценю твою помощь.

Ela Buwa 19.03.2022 10:47
Ответ принят как подходящий

Кажется, что форма имеет какое-то внутреннее состояние. В Shopify есть пакет для управления состоянием формы: @shopify/react-form-state.

В этом примере, если вы хотите, чтобы все было просто, создайте обработчик состояния для каждого поля. Это не медленно, так как реакция группирует вызовы setState при повторной визуализации, и если сделано несколько запросов, страница не будет обновляться в зависимости от количества полей, а только один раз.

const [packageName, setPackageName] = useState("");
const [height, setHeight] = useState("");

async function retrievePackage(){
  setIsLoading(true);
  const response = await axiosInstance.get('/packageInfo?packageId=' + editPackageId);
  setIsLoading(false);
  return response.data;
}

useEffect(() => {
  const data = await retrievePackage();
   
  setPackageName(data.packageName);
  setHeight(data.height);
  ...
}, []);

<TextField
  value = {packageName}
  onChange = {setPackageName}
/>
<TextField
  value = {height}
  onChange = {setHeight}
/>

Затем отправьте объект, состоящий из всех хуков

const formData = {
  packageName,
  height,
}
...

Спасибо. Я получаю «Uncaught TypeError: Невозможно прочитать свойства неопределенного (чтение« значения »)» при обновлении до onChange = {e => setPackageInfo({...packageInfo, packageName: e.target.value})}. Есть идеи? Также попробовал onChange = {e => setPackageInfo({...packageInfo, [packageName]: e.target.value})}. Это происходит, когда я печатаю в текстовом поле. Исходная проблема с заполнением поля packageName только после использования предложенного вами useEffect. Ценю твою помощь.

Ela Buwa 19.03.2022 10:47

При проверке @shopify/полярные документы компонент TextField принимает функцию со значением параметра, а не событие. Я отредактирую свой ответ, чтобы отразить это. Кроме того, скобки в fieldName должны были показывать значение универсальной переменной, то есть имя текущего поля.

Kriss 19.03.2022 14:12

Спасибо, Крисс. Это устранило ошибку, о которой я упоминал. Однако исходная проблема с отображением packageName только в текстовом поле, а не в других, все еще существует. Любая идея, почему это происходит?

Ela Buwa 19.03.2022 20:47

Спасибо разобрался с этим. Судя по всему, модуль не принимает целочисленные значения. Преобразовал его в строку, и это сработало. Еще раз спасибо за помощь.

Ela Buwa 20.03.2022 00:23

Другие вопросы по теме