Overview
We show how Actions and Loaders work to manager working with server for data and to make API calls. In both of the examples presented in video, the actions are processing the form data and then making the appropriate calls to Supabase. We then take the responses we get from Supabase and populate action data which is returned to the page and rendered appropriately.
Remix is a full stack web framework that lets you focus on the user interface and work back through web fundamentals to deliver a fast, slick, and resilient user experience.
The Video
Writing Data
This is the action function related to writing new record to the database. The form that is being processed has an input elements for all of the fields to be written to database. On successful write to database, we redirect back to the default route of application
Using Supabase Database, Built On Posgres
export const action = async ({ request }) => {
// get data from form
let form = await request.formData();
let name = form.get("name");
let description = form.get("description");
let state = form.get("state");
// use form information to write to supabase
const { data, error } = await supabaseClient
.from("chargers")
.insert([{ name, description, state }]);
// if no error, back to home page... index.jsx
if (!error) {
return redirect("/", {});
}
// else stay on page and return error information
return { data, error };
};
Uploading Files
Currently a bug in Remix when uploading large files. In this example I am only using small files to show how the process works
This example is derived from the Remix documentation on uploadHandler which can be found here
Access To Storage Buckets
Creating buckets in Supabase is beyond the scope of this video, you can read more here, but I wanted to include the script for creating the appropriate policy because I got stuck on this issue.
This is the SQL script I used to allow you to upload files to Supabase Storage. I am not restricting access for the purpose of this demo but you can read up more or on creating policy here in the Supabase Documentation
replace my bucket id "images" with the name of your bucket
create policy "ALL images are publicly accessible."
on storage.objects for select
using ( bucket_id = 'images' );
create policy "Anyone can upload an image."
on storage.objects for insert
with check ( bucket_id = 'images' );
create policy "Anyone can update an image."
on storage.objects for update
with check ( bucket_id = 'images' );
This is the action function related to file upload. The form that is being processed has an input element with the id my-file
Using Supabase Buckets
const action = async ({ request }) => {
try {
/**
*
* @param {*} param0
* @returns
*/
let uploadHandler = async ({ name, stream, filename }) => {
console.log("in uploadHandler");
if (name !== "my-file") {
stream.resume();
return;
} else {
console.log(name, filename);
}
// Get the file as a buffer
const chunks = [];
for await (const chunk of stream) chunks.push(chunk);
const buffer = Buffer.concat(chunks);
// call supabase function for uploading to bucket
const { data, error } = await supabaseClient.storage
.from("images")
.upload(filename, buffer);
if (error) {
throw error;
}
// return information up uploaded file
return JSON.stringify({ data });
};
// get file info back after image upload
const form = await unstable_parseMultipartFormData(request, uploadHandler);
//convert it to an object to padd back as actionData
const fileInfo = JSON.parse(form.get("my-file"));
// this is response from upload handler
console.log("the form", form.get("my-file"));
// return success action data
return fileInfo;
} catch (e) {
// return error action data
return { error: e };
}
};
Comments