javascript - 带有来自异步源的嵌套字段数组的 React hook 表单返回空数组

标签 javascript reactjs react-hook-form

关注此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,所以请耐心等待。 我的问题是,如果进一步探测或查询,嵌套字段中的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}].ch​​allenges部分;如果通过console.log显示,它返回一个空数组。如果我从中删除 [${nestIndex}].ch​​allenges ,它将返回完整的数据集(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> );
}

以上工作正常,并显示两个带有上次接收日期的框,这意味着其中的字段保留了我从表单中所需的数据,如下:

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> );
}

所以我剩下的是两个带有上次收到的数据的框,但其中没有列出任何任务,这与我上面链接的示例相去甚远。

我尝试将 TaskFields 的 name 中的 array[${nestIndex}].ch​​allenges 替换为 array,然后将 fields.map 替换为 fields[nestIndex].challenges.map,它确实可以显示数据,但删除按钮确实会删除数组下的整个对象,而不是删除任务下的对象,大概是因为其中的 fields 设置为数组。

有什么我错过的吗?

最佳答案

我在这里看到两件事需要注意

首先,嵌套的是任务而不是挑战

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

其次,您使用了默认状态为空对象 {}challengeData 来在对象不为空时有条件地渲染。但您可能不记得 Boolean({}) === true,因此您可能会意外地从头开始渲染,甚至在获取数据之前也是如此。因此,解决方案可能会使用 Object.keys(challengeData).length > 0 代替,或者为了简单起见,仅使用 fetched 的 bool 值

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}

下面是我的 fork 代码和修复程序

Edit compassionate-galileo-nkz71

关于javascript - 带有来自异步源的嵌套字段数组的 React hook 表单返回空数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63269827/

相关文章:

reactjs - 如何将使用钩子(Hook)的函数包装在 useEffect 中?

javascript - 为 React Hook Form 和 watch() 自定义 onChange

material-ui - React-Testing-Library 找不到具有给定角色和名称的组件

javascript - 如何从 HTML 源刷新/重新加载我的 DataTable

javascript - 如何将节点列表对象传递给后台脚本?

javascript - 录音机未将控制权返回给phonegap应用

HTML/CSS 需要帮助在两个元素之间创建下划线

javascript - Fancybox 弹出一次 session

javascript - 在 Jest 和 Enzyme 测试中触发 useEffect

reactjs - react-hook-form Controller 问题