feat: add support for custom fetch overrides via FormioProvider and F…#642
Open
AyoubSayah wants to merge 1 commit into
Open
feat: add support for custom fetch overrides via FormioProvider and F…#642AyoubSayah wants to merge 1 commit into
AyoubSayah wants to merge 1 commit into
Conversation
Contributor
Author
|
Just to provide some real-world context on why this is so valuable: In one of our active projects, I manually overrode the fetch instance to pipe Form.io's internal network requests through React Query. It worked beautifully and allowed us to leverage all of our existing caching mechanisms. However, doing it via global mutation was messy and caused state to leak across our React component tree. I built this PR so that the rest of the community can cleanly and declaratively integrate tools like React Query directly via props without having to fight the global prototype! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR introduces a React-idiomatic way to provide a custom fetch function to Form.io network requests. It adds a customFetch prop to both the
component and the , eliminating the need for consumers to manually mutate the global Formio.fetch prototype as a side-effect.🕵️♂️ Why are we making this change?
Currently, to customize the fetch function (e.g., for adding authorization headers, integrating React Query, or custom error handling), consumers must mutate the global module:
tsx
import { Formio } from 'formiojs';
Formio.fetch = myCustomFetchFunction; // Global side-effect!
This is problematic in React applications because:
Global Mutation: It affects every Form.io instance across the entire application.
Component: Accepts a customFetch prop. Because @formio/core currently hardcodes network requests to the static Formio.fetch property, the component safely manages this global state internally. It intercepts the form instantiation, safely swaps Formio.fetch to the provided customFetch during initialization, and cleans up after itself on unmount. 🏗️ Architecture Note Because the underlying @formio/core SDK does not currently support instance.fetch (it hardcodes the static Formio.fetch in Formio.request), the React wrapper manages this state via a useEffect cleanup pattern. If/when @formio/core supports true per-instance fetch properties, the internal logic of this React component can be updated with zero breaking changes to the consumer's public API.Not React-Idiomatic: React components should be declarative and configurable via props, not by mutating globals before rendering.
Hard to Test: Testing different forms with different fetch strategies in the same suite causes global state to leak between tests.
🛠️ How is it implemented?
FormioCustomFetch Type: Exported a new type representing the native fetch API signature.
Integration: customFetch can be passed to the provider to act as the default fallback for all nested forms via React Context.
📋 Testing & Verification
{ const response = await fetch(url, { ...init, headers: { ...init?.headers, Authorization: `Bearer ${getToken()}`, }, }); return response; }} /> );✅ Added customFetch.test.tsx testing the prop, the context fallback, override precedence, and unmount restoration.
✅ All 8 tests pass locally.
✅ Updated README.md with full usage examples for single-form and provider-level configurations.
📖 Code Example
tsx
import { Form } from '@formio/react';
// Easily scope fetch behavior to a specific form declaratively
const MyForm = () => (