Формы ловушки React с массивом вложенных полей из источника asyn c возвращают пустой массив - PullRequest
0 голосов
/ 05 августа 2020

Следуя этому примеру вложенных массивов, я пытаюсь отобразить следующие данные:

 { array: [
    {
        { "last_received_date": "2020-08-03 11:04:18 UTC+8", "tasks": [
            { "id": "1", "freq": "d", "prog": 0, "max": 5, "reward": 1000 },
            { "id": "2", "freq": "d", "prog": 0, "max": 1, "reward": 1000 },
            { "id": "3", "freq": "d", "prog": 0, "max": 3, "reward": 1000 }]
        }
    }, 
    { everything like above but more }
]}

Это длинный, и я плохо разбираюсь в реагирую на крючки сам, так что терпите меня. Моя проблема в том, что fields в моем вложенном поле возвращает пустой массив, если он будет исследован или запрошен в дальнейшем. Вот ссылка на созданную мной песочницу (насколько я мог имитируйте его).

Вот вложенное поле:

export default function TaskFields({ nestIndex, control, register, errors }) {
    const { fields, remove } = useFieldArray({ control, 
        name: `array[${nestIndex}].challenges` 
    });
    const indexMap = ['Daily', 'Weekly'];
    return (
        <Box>
            {fields.map((task, j) => { // Should repeat thrice, but fields is apparently empty
                return (
                <Box key={j}>
                    <Button variant="danger" onClick={() => {remove(j);}} size="small" }>x</Button>
                    ID: <input name={indexMap[nestIndex] + `task[${j}].id`}  ref={register()} defaultValue={task.id} />                     
                    Freq: // Same as above
                    Prog: // Same as above
                    Max Prog: // Same as above
                    Reward: // Same as above
                </Box> );
            })}
        </Box> );
}

Обратите внимание на часть name: array[${nestIndex}].challenges; если отображается через console.log, он возвращает пустой массив. Если я удалю из него [${nestIndex}].challenges, он вернет полный набор данных (значение array). Но эта внешняя часть данных уже обработана и отображается здесь:

Основное поле:

export default function TaskTypeCards({ control, register, errors }) {
const { fields } = useFieldArray({ control, name: "array" });   
const indexMap = ['Daily', 'Weekly'];
return (
    <Box>
        {fields.map((item, i) => { // Will repeat twice, since there are two objects in the array
            return (
                <Box key={i}>
                    Title: {indexMap[i]}
                    Last Received Date: // This will display the last received date
                    <TaskFields data={item} nestIndex={i} {...{ control, register, errors }}/> 
                    // This should display the array of objects in 'tasks'
                </Box>
            )
        })}
    </Box> );
}

Вышеупомянутое работает нормально и отображает два поля с Last Received Date, что означает, что fields там сохранили данные, которые мне нужны из формы ниже:

export default UserTaskForm (data) {
    const [challengeData, setChallengeData] = useState({});
    const { register, control, handleSubmit, setError, reset, errors } = useForm(challengeData);
    useEffect(() => {
        async function fetchData() {
            let result = await dbGetUserTasks(data.userId); // Gets results from API
            let challengeData = JSON.parse(result[0].data)); // Looks like the data above
            setChallengeData(challengeData);
            reset(challengeData);
        }
        fetchData();        
    }, [reset]);    
    return (
        <form onSubmit={handleSubmit(onSubmit)}>
            <Button type="submit" style={{ marginLeft: "auto" }}>Save Changes</Button>
            {challengeData ? <TaskTypeCards {...{ control, register, errors }} /> : null}
        </form> );
}

Итак, у меня остались два поля с Last Received Data, но ничего из задач, которые перечислены в нем, что далеко от примера, который я привел выше.

Я попытался заменить array[${nestIndex}].challenges только array в name TaskFields, а затем заменил fields.map на fields[nestIndex].challenges.map, который действительно работает при отображении данных, но кнопка удаления удаляет весь объект в массиве, а не объект в задачах, предположительно потому, что fields установлен в массив.

Есть что-нибудь, что я пропустили?

1 Ответ

2 голосов
/ 05 августа 2020

Я заметил здесь две вещи

Во-первых, вложенный: tasks not challenges

// UserTaskFields.js
// ...
const { fields, remove } = useFieldArray({
  control,
  name: `array[${nestIndex}].tasks`,
})
// ...

Во-вторых, вы использовали challengeData с пустым состоянием по умолчанию. объект {} для условного рендеринга, если объект не пустой. Но вы можете не помнить этот Boolean({}) === true, чтобы случайно выполнить рендеринг с самого начала, даже до получения данных. Таким образом, решение может использовать вместо этого Object.keys(challengeData).length > 0 или просто использовать логическое значение fetched для простоты

const x = {}

console.log(Boolean(x))

console.log(x ? 'foo' : 'bar')
// UserTaskForm.js
const [challengeData, setChallengeData] = useState({});
const [fetched, setFetched] = useState({});
// ...

// This will always render because Boolean({}) return true
{challengeData ? <TaskTypeCards {...{ control, register, errors }} /> : null}

// => should be
{Object.keys(challengeData).length > 0 ? <TaskTypeCards {...{ control, register, errors }} /> : null}

// => other way
{fetched? <TaskTypeCards {...{ control, register, errors }} /> : null}

Ниже мои разветвленные коды и ящик с исправлением

Изменить compassionate-galileo-nkz71

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...