我正在使用React Hook Form来构建一个基本的页面构建器应用程序,到目前为止它非常出色,我一直在使用useFieldArray钩子来创建包含项目的列表,但是,我还没有找到在列表之间移动项目的方法。
我知道我可以使用move()函数来重新排序同一列表中的项,但是,由于每个列表都有自己嵌套的useFieldArray,我不能将项从一个列表组件移动到另一个列表组件。
如果有人知道解决这个问题的方法,将不胜感激!
下面是我当前设置的一个非常简化的例子:
export const App = () => {
const methods = useForm({
defaultValues: {
lists: [
{
list_id: 1,
items: [
{
item_id: 1,
name: 'Apple'
},
{
item_id: 2,
name: 'Orange'
}
]
},
{
list_id: 2,
items: [
{
item_id: 3,
name: 'Banana'
},
{
item_id: 4,
name: 'Lemon'
}
]
}
]
}
});
return (
<FormProvider {...methods}>
<Page/>
</FormProvider>
)
}
export const Page = () => {
const { control } = useFormContext();
const { fields } = useFieldArray({
control,
name: 'lists'
})
return (
<ul>
{fields?.map((field, index) => (
<List listIdx={index} />
))}
</ul>
)
}
export const List = ({ listIdx }) => {
const { control, watch } = useFormContext();
const { fields, move } = useFieldArray({
control,
name: `lists[${sectionIdx}].items`
})
const handleMove = (prevIdx, nextIdx) => {
// this allows me to move within lists but not between them
move(prevIdx, nextIdx);
}
return (
<li>
<p>ID: {watch(lists[${listIdx}].list_id)}</p>
<ul>
{fields?.map((field, index) => (
<Item listIdx={index} itemIdx={index} handleMove={handleMove}/>
))}
</ul>
</li>
)
}
export const Item = ({ listIdx, itemIdx, handleMove }) => {
const { control, register } = useFormContext();
return (
<li>
<p>ID: {watch(lists[${listIdx}].items[${itemIdx}].item_id)}</p>
<label
Name:
<input { ...register('lists[${listIdx}].items[${itemIdx}]) }/>
/>
<button onClick={() => handleMove(itemIdx, itemIdx - 1)}>Up</button>
<button onClick={() => handleMove(itemIdx, itemIdx + 1)}>Down</button>
</div>
)
}
提前感谢!
如果你不想改变你的默认值(你的数据结构),我认为处理这个问题的最好方法是从useFieldArray
返回的update
方法。你有两个将要移动的输入的数据,知道它们的列表索引和项目索引,你可以很容易地用彼此的数据更新它们的当前位置。