reduxjs / redux-toolkit

The official, opinionated, batteries-included toolset for efficient Redux development
https://redux-toolkit.js.org
MIT License
10.63k stars 1.15k forks source link

Feature request: pass `pollingInterval` a function #4199

Open harry-gocity opened 6 months ago

harry-gocity commented 6 months ago

Use case:

Here's a rough WIP of how I would see this looking in practice:

export const PaymentForm = (): ReactElement => {
    const [shouldPoll, setShouldPoll] = useState(false);

    const [createOrder, { data: createdOrder }] = useCreateOrderMutation();

    const { data: orderStatus, isSuccess: hasOrderStatus } = useGetOrderStatusQuery(
        createdOrder ? { orderNumber: createdOrder.orderNumber } : skipToken,
        { pollingInterval: shouldPoll ? 1000 : 0 }
    );

    if (shouldPoll && hasOrderStatus && orderStatus.paymentStatus === 'FAILED') {
        setShouldPoll(false);
    }

    if (orderStatus.paymentStatus === 'SUCCESS') {
        // navigate to confirmation page
    }

    const handleSubmit = () => {
        createOrder()
            .unwrap()
            .then(() => {
                setShouldPoll(true);
            })
            .catch(() => {
                setShouldPoll(false);
            });
    };

    return (
        <div>
            <form onSubmit={handleSubmit} />
            {/* Something using orderStatus */}
        </div>
    );
};

I'd like to be able to eliminate the need for the shouldPoll status, which I'm currently updating after unwrapping createOrder and comparing/updating in render.

If pollingInterval accepted a callback that received the current query data (and possibly other flags like isSuccess) I could use the current state of the data to determine if the query should keep polling:

const { data: orderStatus, isSuccess: hasOrderStatus } = useGetOrderStatusQuery(
    createdOrder ? { orderNumber: createdOrder.orderNumber } : skipToken,
    {
        pollingInterval: (data) => (data?.paymentStatus === 'FAILED' ? 0 : 1000),
    }
);

With this in place, if a payment fails:

I then no longer need local state or to unwrap my mutation result in handleSubmit.

Tanstack Query has a similar API via refetchInterval - https://tanstack.com/query/latest/docs/framework/react/reference/useQuery

The possible drawbacks I can see are:

I think this could be done without a breaking change given the option currently only accepts a number.

opswiz commented 4 months ago

This would be very helpful to manage polling dynamically based on response. Currently workarounds are needed and not clean.