Working with Forms ​
This guide covers how to work with forms using Flowfull Client.
Basic Form Handling ​
Flowfull Client doesn't include built-in form components, but it's easy to integrate with standard forms:
React Example ​
typescript
import { useState } from 'react';
import { api } from '../lib/api';
function CreateUserForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
setError('');
try {
const user = await api.post('/users', formData);
console.log('User created:', user);
// Reset form
setFormData({ name: '', email: '', password: '' });
// Show success message or redirect
alert('User created successfully!');
} catch (err: any) {
setError(err.message || 'Failed to create user');
} finally {
setLoading(false);
}
}
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setFormData({
...formData,
[e.target.name]: e.target.value
});
}
return (
<form onSubmit={handleSubmit}>
<div>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
placeholder="Name"
required
/>
</div>
<div>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="Email"
required
/>
</div>
<div>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
placeholder="Password"
required
/>
</div>
<button type="submit" disabled={loading}>
{loading ? 'Creating...' : 'Create User'}
</button>
{error && <div style={{ color: 'red' }}>{error}</div>}
</form>
);
}Update Forms ​
typescript
import { useState, useEffect } from 'react';
import { api } from '../lib/api';
function EditUserForm({ userId }: { userId: string }) {
const [formData, setFormData] = useState({
name: '',
email: ''
});
const [loading, setLoading] = useState(false);
const [fetching, setFetching] = useState(true);
useEffect(() => {
// Fetch user data
async function fetchUser() {
try {
const user = await api.get(`/users/${userId}`);
setFormData({
name: user.name,
email: user.email
});
} catch (error) {
console.error('Error fetching user:', error);
} finally {
setFetching(false);
}
}
fetchUser();
}, [userId]);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
try {
const updated = await api.put(`/users/${userId}`, formData);
console.log('User updated:', updated);
alert('User updated successfully!');
} catch (error: any) {
alert(error.message || 'Failed to update user');
} finally {
setLoading(false);
}
}
if (fetching) return <div>Loading...</div>;
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
placeholder="Name"
/>
<input
type="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
placeholder="Email"
/>
<button type="submit" disabled={loading}>
{loading ? 'Updating...' : 'Update User'}
</button>
</form>
);
}File Upload Forms ​
typescript
function UploadForm() {
const [file, setFile] = useState<File | null>(null);
const [loading, setLoading] = useState(false);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!file) return;
setLoading(true);
try {
const formData = new FormData();
formData.append('file', file);
formData.append('name', 'My File');
const response = await api.post('/upload', formData);
console.log('File uploaded:', response);
alert('File uploaded successfully!');
} catch (error: any) {
alert(error.message || 'Upload failed');
} finally {
setLoading(false);
}
}
return (
<form onSubmit={handleSubmit}>
<input
type="file"
onChange={(e) => setFile(e.target.files?.[0] || null)}
/>
<button type="submit" disabled={!file || loading}>
{loading ? 'Uploading...' : 'Upload'}
</button>
</form>
);
}Next Steps ​
- Making API Calls - Learn more about API calls
- Data Fetching - Advanced data fetching patterns
- TypeScript Usage - Get the most out of TypeScript