我正在做一个NextJS项目,遇到了一个问题,在表单提交后视图没有更新,我使用react-query
来获取数据和进行转换。
我有一个名为“添加日期”的表单,它通过端点向数据库添加一个日期对象。但是在进行此更新后,我的UI没有刷新以反映此新对象。
下面是一个视频演示它:
https://imgur.com/a/KIcQOfs
如您所见,当我刷新页面时,视图也会更新。但我希望它在我提交表单并成功提交后立即更新。下面是我的代码设置:
行程详情
const TripDetailPage = () => {
const router = useRouter()
const queryClient = useQueryClient()
const tripId = router.query.tripId as string
const { data, isError, isLoading } = useQuery({
queryKey: ['trips', tripId],
queryFn: () => getTrip(tripId),
})
const [tabState, setTabState] = useState(1)
const toggleTab = (index: number) => {
setTabState(index)
}
const [modalVisible, setModalVisible] = useState<boolean>(false)
const toggleModalVisible = () => {
setModalVisible(!modalVisible)
}
const onDayAdded = () => {
queryClient.invalidateQueries({ queryKey: ['trips', tripId] })
console.log('refetching')
console.log('day was added')
}
console.log('new data?')
console.log(data)
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return <span>Error</span>
}
if (!data || !data.data || !data.data.name || !data.data.days) {
return <span>Error</span>
}
return (
<div className="ml-12 mr-12 mt-6">
<div className="flex flex-row justify-between">
<div className="order-first flex items-center">
<h1 className="text-2xl font-semibold text-slate-800">{data.data.name}</h1>
<Button className="btn btn-primary ml-8">Invite</Button>
</div>
<div className="order-last flex">
<Button className="btn btn-primary mr-4">Refresh</Button>
<Button className="btn btn-primary" onClick={toggleModalVisible}>
Add Day
</Button>
</div>
<AddDayModal
onSuccess={onDayAdded}
modalVisible={modalVisible}
toggleModalVisible={toggleModalVisible}
trip={data.data}
/>
</div>
<div id="tabs-nav" className="font-medium text-lg border-separate pb-2 border-b-2 border-gray-200 mt-6">
<TabButton tabId={1} currentTabState={tabState} name="Plans" toggleTab={() => toggleTab(1)}></TabButton>
<TabButton
tabId={2}
currentTabState={tabState}
name="Calendar"
toggleTab={() => toggleTab(2)}
></TabButton>
<TabButton tabId={3} currentTabState={tabState} name="Ideas" toggleTab={() => toggleTab(3)}></TabButton>
</div>
<div id="content">
{tabState === 1 && <PlannerBoard days={data.data.days} tripId={tripId}></PlannerBoard>}
{tabState === 2 && <h1>Tab 2</h1>}
{tabState === 3 && <h1>Tab 3</h1>}
</div>
</div>
)
}
export default TripDetailPage
我在onDayAdded
中调用invalidateQueries
,它应该会重新获取我的数据并更新我的视图,但似乎没有。PlannerBoard
是我传递数据的地方,也是呈现列的组件。它基本上迭代传递给它的days
并呈现它们。
规划板:
type TDndPlannerProps = {
days: TDay[]
tripId: string
}
const PlannerBoard = (props: TDndPlannerProps) => {
// ...
props.days.forEach((day) => {
// lots of processing, creates a data object which has the objects to make this view
})
const [state, setState] = useState<IData>(data) // after above processing
// removed a bunch of code
return (
<div className="overflow-auto">
<div>
{day.map((day) => {
return <DayColumn key={day.id} day={day} />
})}
</div>
</div>
)
}
export default PlannerBoard
AddDay模态:
type TModalProps = {
trip: TTrip
modalVisible: boolean
toggleModalVisible: () => void
onSuccess: () => void
}
const formArr: TFormField[] = [
{
label: 'Day name',
name: 'name',
type: 'text',
},
{
label: 'Day date',
name: 'date',
type: 'date',
},
]
const AddDayModal = (props: TModalProps) => {
const [day, setDay] = useState<TDay>({
name: '',
tripId: props.trip.id!,
})
const onSuccess = () => {
props.toggleModalVisible()
props.onSuccess()
}
const { mutate, isLoading, isError, error } = useMutation((day: TDay) => postDay(day), { onSuccess })
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
mutate(day)
}
const onUpdate = (update: TFormFieldValue) => {
setDay((prev) => {
if (update.type == 'date') {
return { ...prev, [update.name]: new Date(update.value) }
} else {
return { ...prev, [update.name]: update.value }
}
})
}
const formModalProps: TFormModalProps = {
title: 'Add Day',
formArr,
submitBtn: 'Submit',
submittingBtn: 'Adding',
toggleVisible: props.toggleModalVisible,
visible: props.modalVisible,
onSubmit,
isLoading,
isError,
error,
onUpdate,
}
return (
<div>
<FormModal {...formModalProps} />
</div>
)
}
export default AddDayModal
这里的mutate
调用了我的API,用这个表单数据更新了数据库,一旦我们点击了onSuccess
,API调用就成功了,它调用了TripDetailPage的onDayAdded()
。
知道如何在重取完成后更新UI吗?我需要使用useState
吗?
2条答案
按热度按时间bmp9r5qi1#
我相信这是react-query的预期行为。
您可以使用
queryClient.invalidateQueries
在该高速缓存中重取单个或多个查询,也可以使用queryClient.setQueryData
立即更新查询的缓存数据。如果愿意,您可以直接在
onSuccess
回调中使用它。参见documentation。
snz8szmq2#
我相信我有一个修复。在我的
PlannerBoard
中,我需要通过useEffect
检测 prop 的变化,然后再次手动设置状态为:这将强制视图重新渲染。