javascript 在NextJS中使用react-query提交表单数据后React更新视图

gv8xihay  于 2023-01-01  发布在  Java
关注(0)|答案(2)|浏览(276)

我正在做一个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吗?

bmp9r5qi

bmp9r5qi1#

我相信这是react-query的预期行为。
您可以使用queryClient.invalidateQueries在该高速缓存中重取单个或多个查询,也可以使用queryClient.setQueryData立即更新查询的缓存数据。
如果愿意,您可以直接在onSuccess回调中使用它。
参见documentation

snz8szmq

snz8szmq2#

我相信我有一个修复。在我的PlannerBoard中,我需要通过useEffect检测 prop 的变化,然后再次手动设置状态为:

useEffect(() => {
    const data: IData = createBoardData(props.days)
    setState(data)
}, [props])

这将强制视图重新渲染。

相关问题