I am trying to make a form to submit data to supabase (with nextjs 13).
I can submit a string input. I am trying to add a boolean field.
I have commented out the 'published' fields in this form. If I try using this approach, and enter any of 'true' 'TRUE' 0 1 'false' or 'FALSE' in the input field, I get no errors in the console (none of my error flags produce a result, and I cannot even console log the enter key having been pressed.
I have also tried using a checkbox as shown below. When I try, I get an error that says:
TypeError: Cannot read properties of undefined (reading 'published')
This error doesn't make sense to me because when I hover over feeds in this state handler, I get a list of the attributes on feeds (and published is a boolean attribute defined there, with a default value of false).
form:
"use client"
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { useEffect, useState } from 'react'
import { addFeed } from "./actions/newFeedFormSubmit"
type Feeds = Database['public']['Tables']['feeds']['Row']
export default function Feed( {feed}: { feed: Feeds;} ) {
const [isPublished, setIsPublished] = useState(feed.published )
const action = async (formData: FormData) => {
const result = await addFeed(formData) // addTweet is a server action, define it in a separate file
if (result?.error) {
console.log(result.error.message)
} else {
console.log(" added successfully")
// resetting input field
}
}
const [feeds, setFeeds] = useState<any[]>([])
// Create a Supabase client configured to use cookies
const supabase = createClientComponentClient<Database>()
useEffect(() => {
const getFeeds = async () => {
// This assumes you have a `todos` table in Supabase. Check out
// the `Create Table and seed with data` section of the README
// https://github.com/vercel/next.js/blob/canary/examples/with-supabase/README.md
const { data } = await supabase.from('feeds').select()
if (data) {
setFeeds(data)
}
}
getFeeds()
}, [supabase, setFeeds])
return (
<div>
<form
action={action}
>
<input name="title" className="bg-inherit" />
{/* <input name="published" className="bg-inherit" /> */}
<input
name="published"
className="cursor-pointer"
onChange={() => setIsPublished(isPublished)}
// onChange={(e) => toggle()}
type="checkbox"
checked={isPublished ? true : false}
/>
</form>
<pre>{JSON.stringify(feeds, null, 2)}</pre>
</div>
);
}
form action:
"use server"
import { revalidatePath } from "next/cache"
import { cookies } from "next/headers"
import { createServerActionClient } from "@supabase/auth-helpers-nextjs"
export const addFeed = async (formData: FormData) => {
const title = String(formData.get("title"))
const published = Boolean(formData.get("published"))
const supabase = createServerActionClient<Database>({ cookies })
const {
data: { user },
} = await supabase.auth.getUser()
if (!user) {
throw new Error("No user found")
}
if (!title) {
return { error: { message: "Please enter a title" } }
}
try {
const { error } = await supabase
.from("feeds")
.insert({ title, published, created_by: user.id })
if (error) throw new Error(error.message)
} catch (error) {
console.error(error)
}
revalidatePath("/")
}
This documentation doesn't tell me how to apply a radio button to match the boolean choice.
Can anyone show me how to use a boolean data type in a supabase form input?
NEXT ATTEMPT
Chat gpt4 has given me a solution that works to submit to supabase where a boolean attribute is included in the data being submitted, but it is not using server actions as shown in the nextjs documentation.
The form has:
"use client"
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
import { useEffect, useState } from 'react';
import { addFeed } from "./actions/newFeedFormSubmit";
type Feeds = Database['public']['Tables']['feeds']['Row'];
export default function Feed({ feed }: { feed: Feeds; }) {
const [isPublished, setIsPublished] = useState(feed?.published || false);
const [feeds, setFeeds] = useState<any[]>([]);
const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget as HTMLFormElement);
try {
await addFeed(formData);
console.log("Feed added successfully");
// You can reset the form or redirect the user, etc. here
} catch (error) {
if (error && typeof error === 'object' && "message" in error) {
console.error("Error from server action:", error.message);
}
}
};
return (
<div>
<form onSubmit={handleFormSubmit}>
<input name="title" className="bg-inherit" />
<input
name="published"
className="cursor-pointer"
type="checkbox"
checked={isPublished}
onChange={() => setIsPublished(prev => !prev)}
/>
<button type="submit">Submit</button>
</form>
<pre>{JSON.stringify(feeds, null, 2)}</pre>
</div>
);
}
The form action has:
"use server"
import { revalidatePath } from "next/cache";
import { cookies } from "next/headers";
import { createServerActionClient } from "@supabase/auth-helpers-nextjs";
export const addFeed = async (formData: FormData) => {
const title = String(formData.get("title"));
const published = Boolean(formData.has("published")) && formData.get("published") === 'on';
const supabase = createServerActionClient<Database>({ cookies });
const { data: { user } } = await supabase.auth.getUser();
if (!user) throw new Error("No user found");
if (!title) throw new Error("Please enter a title");
console.log("attempting to add feed", { title, published });
const { error } = await supabase.from("feeds").insert({ title, published, created_by: user.id });
if (error) throw new Error(error.message);
revalidatePath("/");
}
Can anyone help figuring out why I can't use server actions to submit a form (in the format shown in the nextjs documentation, if the form data includes a boolean attribute?
thank you