使用来自异步源 returns 空数组的嵌套字段数组反应挂钩表单
React hook forms with nested fields array from an async source returns empty array
在这个 example 嵌套数组之后,我试图显示以下数据:
{ 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 }
]}
篇幅较长,本人对react hooks不是很了解,还请多多包涵。 我的问题是,如果进一步探测或查询,我的嵌套字段 returns 中的 fields
是一个空数组。 这是沙盒的 link我做了(尽我所能模仿)。
这是嵌套字段:
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
显示,它 returns 是一个空数组。如果我从中删除 [${nestIndex}].challenges
,它会 returns 完整的数据集(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
的框,但其中没有列出任何任务,这与我上面链接的示例相去甚远。
我尝试在 TaskFields 的 name
中将 array[${nestIndex}].challenges
替换为 array
,然后将 fields.map
替换为 fields[nestIndex].challenges.map
在显示数据时起作用,但删除按钮确实删除了数组下的整个对象,而不是任务下的对象,大概是因为 fields
设置为数组。
有什么我遗漏的吗?
我看到这里有两点需要注意
首先是嵌套是tasks
不是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}
下面是我的带有修复程序的分叉代码和框
在这个 example 嵌套数组之后,我试图显示以下数据:
{ 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 }
]}
篇幅较长,本人对react hooks不是很了解,还请多多包涵。 我的问题是,如果进一步探测或查询,我的嵌套字段 returns 中的 fields
是一个空数组。 这是沙盒的 link我做了(尽我所能模仿)。
这是嵌套字段:
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
显示,它 returns 是一个空数组。如果我从中删除 [${nestIndex}].challenges
,它会 returns 完整的数据集(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
的框,但其中没有列出任何任务,这与我上面链接的示例相去甚远。
我尝试在 TaskFields 的 name
中将 array[${nestIndex}].challenges
替换为 array
,然后将 fields.map
替换为 fields[nestIndex].challenges.map
在显示数据时起作用,但删除按钮确实删除了数组下的整个对象,而不是任务下的对象,大概是因为 fields
设置为数组。
有什么我遗漏的吗?
我看到这里有两点需要注意
首先是嵌套是tasks
不是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}
下面是我的带有修复程序的分叉代码和框