React-Admin中如何在表单外部创建引用输入组件?
Hey there! The error you're seeing happens because react-admin's ReferenceInput (and most of its built-in input components) depend on the useField hook, which requires the context provided by react-admin's <Form> component. That's why placing it outside a form throws the useField must be used inside of a <Form> component error.
Instead of forcing it into a form (which would require dealing with unnecessary form props), you can build a custom, form-independent component using react-admin's data-fetching hooks and standard UI components. Here's a step-by-step solution:
Step 1: Build the Custom Selector Component
We'll use react-admin's useReference hook to fetch the posts data, manage selection state with React's useState, and use MUI components for the UI (since react-admin is built on MUI anyway):
import { useReference } from 'react-admin'; import { Autocomplete, TextField, Button } from '@mui/material'; import { useState } from 'react'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; // Custom component that works outside any form const PostDateSelector = ({ onGenerate }) => { // Manage local state for selected values const [selectedPostId, setSelectedPostId] = useState(null); const [selectedDate, setSelectedDate] = useState(null); // Fetch posts data using react-admin's useReference (no Form context needed!) const { data: posts, isLoading } = useReference({ reference: 'posts', pagination: { page: 1, perPage: 100 }, // Adjust pagination as needed sort: { field: 'title', order: 'ASC' }, // Add a filter here if you need to narrow down posts: // filter: { status: 'published' } }); // Trigger your generate function with the selected values const handleGenerate = () => { if (selectedPostId && selectedDate) { onGenerate(selectedPostId, selectedDate); } }; return ( <div style={{ display: 'flex', gap: '1rem', alignItems: 'flex-end' }}> {/* Custom post selector (replaces ReferenceInput + AutocompleteInput) */} <Autocomplete disabled={isLoading} options={posts || []} getOptionLabel={(post) => post.title} onChange={(event, selectedPost) => setSelectedPostId(selectedPost?.id || null)} renderInput={(params) => ( <TextField {...params} label="Post" variant="outlined" /> )} /> {/* Date selector (replaces DateInput) */} <LocalizationProvider dateAdapter={AdapterDayjs}> <DatePicker label="Date" value={selectedDate} onChange={(newDate) => setSelectedDate(newDate)} renderInput={(params) => <TextField {...params} variant="outlined" />} /> </LocalizationProvider> {/* Generate button */} <Button variant="contained" onClick={handleGenerate} disabled={!selectedPostId || !selectedDate} > Generate </Button> </div> ); }; // How to use the component in your app // <PostDateSelector // onGenerate={(postId, date) => { // // Call your generate function here // console.log('Generating with post ID:', postId, 'and date:', date); // }} // />
Key Details Explained
useReference: This react-admin hook fetches data from yourpostsresource without needing a Form context. You can adjust pagination, sorting, and filtering to match your needs.- Local State: We use
useStateto track the selected post ID and date, so we don't rely on react-admin's form state management. - MUI Components: We use MUI's native
AutocompleteandDatePickerinstead of react-admin's input components, which lets us avoid the Form context requirement.
Additional Notes
- If you need to fetch more posts than the initial
perPagevalue, you can add pagination logic to the component. - If your project uses a different date library (like Moment.js instead of Day.js), swap out the MUI date adapter accordingly.
- You can style the component to match your app's design by adjusting the inline styles or using MUI's theme system.
内容的提问来源于stack exchange,提问作者R H




