-
Hi all, I am not sure how to use the FileTrigger component within a form as a replacement for a , as it does not accept a 'name' in the same way that an input field does. How should I use this component correctly, such that I can get the file from the request formData? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 3 replies
-
See #5486 (comment) |
Beta Was this translation helpful? Give feedback.
-
So actually, we intentionally decided to move FileTrigger away from forms which you can see in this PR.. This might be confusing and I'm sure we can update our docs to help clarify this. One of the follow-ups was to create a separate file input component that works specifically for forms but this has not been implemented yet. |
Beta Was this translation helpful? Give feedback.
-
i just ran into this 😭 i'm using
|
Beta Was this translation helpful? Give feedback.
-
For future readers, you can get started with this in the meanwhile: // FileField.tsx
import { useFormValidation } from '@react-aria/form';
import { useFormValidationState } from '@react-stately/form';
import { type PropsWithChildren, useMemo, useRef } from 'react';
import { FieldErrorContext, InputContext } from 'react-aria-components';
export const FileField = ({
children,
name,
isRequired,
accept,
multiple,
}: PropsWithChildren<{
name?: string | undefined;
isRequired?: boolean | undefined;
accept?: string | undefined;
multiple?: boolean | undefined;
}>): JSX.Element => {
const inputRef = useRef<HTMLInputElement>(null);
const formValidationState = useFormValidationState({
value: undefined,
validationBehavior: 'native',
});
useFormValidation(
{ validationBehavior: 'native' },
formValidationState,
inputRef,
);
const inputProps = useMemo(
() => ({
name,
required: isRequired,
accept,
multiple,
ref: inputRef,
'aria-invalid': formValidationState.displayValidation.isInvalid,
}),
[name, isRequired, accept, multiple, formValidationState],
);
return (
<div
data-required={!!isRequired || undefined}
data-invalid={
formValidationState.displayValidation.isInvalid || undefined
}
>
<InputContext.Provider value={inputProps}>
<FieldErrorContext.Provider
value={formValidationState.displayValidation}
>
{children}
</FieldErrorContext.Provider>
</InputContext.Provider>
</div>
);
}; // FileInput.tsx
import { type ChangeEvent, useCallback, useRef, useState } from 'react';
import { Button, Input } from 'react-aria-components';
export const FileInput = (): JSX.Element => {
const inputRef = useRef<HTMLInputElement>(null);
const [files, setFiles] = useState<File[]>();
const onPress = useCallback(() => {
if (!inputRef.current) return;
if (inputRef.current.value !== '') inputRef.current.value = '';
inputRef.current.click();
}, []);
const onChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
setFiles(event.target.files ? [...event.target.files] : undefined);
}, []);
return (
<div>
<Button onPress={onPress}>Browse...</Button>
<div>{files?.map((x) => <div key={x.name}>{x.name}</div>)}</div>
<Input
style={{ display: 'none' }}
type="file"
ref={inputRef}
onChange={onChange}
/>
</div>
);
}; Use the same way you would use |
Beta Was this translation helpful? Give feedback.
So actually, we intentionally decided to move FileTrigger away from forms which you can see in this PR.. This might be confusing and I'm sure we can update our docs to help clarify this. One of the follow-ups was to create a separate file input component that works specifically for forms but this has not been implemented yet.