You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过ReferenceProvider实现多<SelectInput>共享同一数据源?

Optimizing Multiple Reference Inputs for Shared Data in React Admin

Great question! This is a super common pain point when working with multiple reference inputs that pull from the same resource—all those duplicate API requests can really drag down performance. Luckily, React Admin gives you a couple of solid ways to share a single data source across all 8 of your <SelectInput> components, eliminating redundant network calls.

Option 1: Fetch Data Once with useGetList (Simplest Approach)

The most straightforward fix is to use React Admin's useGetList hook to fetch your font data once, then pass the pre-fetched options to every <SelectInput>. This cuts your API requests from 8 down to 1.

Here's how to implement it:

import { useGetList, SelectInput, Form } from 'react-admin';

const FontConfigurationForm = () => {
  // Fetch all fonts in a single request
  const { data: fonts, isLoading, error } = useGetList('fonts', {
    pagination: { page: 1, perPage: 1000 }, // Adjust perPage if you have lots of fonts
    sort: { field: 'id', order: 'ASC' },
    filter: {},
  });

  // Handle loading/error states
  if (isLoading) return <div>Loading font options...</div>;
  if (error) return <div>Failed to load fonts: {error.message}</div>;

  // Format data for SelectInput (matches your original optionText="id")
  const fontOptions = fonts.map(font => ({ id: font.id, name: font.id }));

  return (
    <Form>
      {/* Primary font weights */}
      <SelectInput
        source="fonts.primary.regular"
        label="Primary Regular"
        options={fontOptions}
      />
      <SelectInput
        source="fonts.primary.bold"
        label="Primary Bold"
        options={fontOptions}
      />
      <SelectInput
        source="fonts.primary.light"
        label="Primary Light"
        options={fontOptions}
      />
      <SelectInput
        source="fonts.primary.black"
        label="Primary Black"
        options={fontOptions}
      />

      {/* Secondary font weights */}
      <SelectInput
        source="fonts.secondary.regular"
        label="Secondary Regular"
        options={fontOptions}
      />
      <SelectInput
        source="fonts.secondary.bold"
        label="Secondary Bold"
        options={fontOptions}
      />
      <SelectInput
        source="fonts.secondary.light"
        label="Secondary Light"
        options={fontOptions}
      />
      <SelectInput
        source="fonts.secondary.black"
        label="Secondary Black"
        options={fontOptions}
      />
    </Form>
  );
};

Pros & Cons

  • Pros: No extra context setup, easy to understand, full control over data formatting.
  • Cons: You lose some of React Admin's built-in reference input features (like automatic refetch on resource updates) unless you implement them manually.

Option 2: Use ReferenceContextProvider (React Admin-Native Approach)

If you want to stay closer to React Admin's ecosystem and retain features like automatic refetching, you can create a custom context provider using React Admin's internal ReferenceContextProvider. This lets all child <SelectInput> components share the same fetched data without duplicate requests.

Here's how to set this up:

import { ReferenceContextProvider, SelectInput, useGetList, Form } from 'react-admin';

// Custom provider to share font data
const FontReferenceProvider = ({ children }) => {
  const { data: fonts, isLoading, error, refetch } = useGetList('fonts', {
    pagination: { page: 1, perPage: 1000 },
    sort: { field: 'id', order: 'ASC' },
    filter: {},
  });

  if (isLoading) return <div>Loading font options...</div>;
  if (error) return <div>Failed to load fonts: {error.message}</div>;

  // Format the context value to match React Admin's expected structure
  const referenceContext = {
    data: fonts,
    total: fonts.length,
    loaded: true,
    loading: false,
    error: null,
    refetch,
  };

  return (
    <ReferenceContextProvider value={referenceContext} resource="fonts">
      {children}
    </ReferenceContextProvider>
  );
};

// Use the provider in your form
const FontConfigurationForm = () => {
  return (
    <FontReferenceProvider>
      <Form>
        {/* Primary font weights */}
        <SelectInput
          source="fonts.primary.regular"
          label="Primary Regular"
          optionText="id"
        />
        <SelectInput
          source="fonts.primary.bold"
          label="Primary Bold"
          optionText="id"
        />
        <SelectInput
          source="fonts.primary.light"
          label="Primary Light"
          optionText="id"
        />
        <SelectInput
          source="fonts.primary.black"
          label="Primary Black"
          optionText="id"
        />

        {/* Secondary font weights */}
        <SelectInput
          source="fonts.secondary.regular"
          label="Secondary Regular"
          optionText="id"
        />
        <SelectInput
          source="fonts.secondary.bold"
          label="Secondary Bold"
          optionText="id"
        />
        <SelectInput
          source="fonts.secondary.light"
          label="Secondary Light"
          optionText="id"
        />
        <SelectInput
          source="fonts.secondary.black"
          label="Secondary Black"
          optionText="id"
        />
      </Form>
    </FontReferenceProvider>
  );
};

Pros & Cons

  • Pros: Integrates seamlessly with React Admin's lifecycle, retains automatic refetch capabilities, works with other reference-based inputs (like AutocompleteInput).
  • Cons: Requires a bit more setup to match the context structure React Admin expects.

Bonus Tip: Bulk Set Default Values

Since you mentioned wanting to assign the same value to all fields when layout changes are minimal, you can add a button to set all inputs to a single selected font. Here's a quick example using React Admin's useForm hook:

import { useForm } from 'react-admin';

// Inside your form component
const { change } = useForm();

const setAllFonts = (fontId) => {
  const fontFields = [
    'fonts.primary.regular',
    'fonts.primary.bold',
    'fonts.primary.light',
    'fonts.primary.black',
    'fonts.secondary.regular',
    'fonts.secondary.bold',
    'fonts.secondary.light',
    'fonts.secondary.black',
  ];
  fontFields.forEach(field => change(field, fontId));
};

// Add this button somewhere in your form
<button onClick={() => setAllFonts('default-font-id')}>Set All Fonts to Default</button>

内容的提问来源于stack exchange,提问作者Hein Haraldson Berg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:15:39