I have a table that looks like the below.
The indivudual rows can be edited, by clicking edit and changing their content. What I need now is that: where it's yellow i need the filter to be. So when someone enters something like at Last Name like: "Joh" All entries that match with "Joh" should be displayed.
In a nutshell my code looks like this in the app:
/** page.js **/
import connection from "/lib/db";
import {format} from "date-fns";
import Image from "next/image";
import ClientTableRow from "@/components/ClientTableRow";
export default async function Home() {
/**
* @type {{id: number, name: string, last_name: string, phone: string, email: string,
created_at: string}[]}
*/
let data = [];
try {
const [rows] = await connection.query('SELECT * FROM clients');
data = rows.map(row => ({
...row,
created_at: format(new Date(row.created_at), 'dd-MM-yyyy HH:mm:ss')
}));
} catch (error) {
console.error('Error fetching data:', error.message);
}
return (
<table className="min-w-full divide-y divide-gray-300">
<thead className="bg-gray-50">
<tr>
{/*filter should be here*/}
<td>ID</td>
<td>Name</td>
<td>Last name</td>
<td>Phone</td>
<td>Email</td>
<td>Created at</td>
<td></td>
</tr>
</thead>
<tbody className="divide-y divide-gray-200 bg-white">
{data.map((item, index) => (
<ClientTableRow key={index} client={item}/>
))}
</tbody>
</table>
);
I also have an actions.js and a ClientTableRow.js file. I don't think the code is needed.
The question: How do i update the fields dynamically without reloading the page? I know how to do this with pure frontend react, i'm not sure how to handle this with nextjs. I am assuming it might be possible with partial rehydration and server actions?
What you've created is a React Server Page - it is allowed be invoked async, but does not permit any interactivity/dynamic scripts. Instead, you have to make it a React Client Page. Here's a sketch - the filter thingy is a bit unclear and I think out of the scope of question on how to avoid reloading. Here's a sketch where I left the filter aspect out mostly.
'use client'; // Now, this is not a React Server Component anymore
import connection from '/lib/db';
import { format } from 'date-fns';
import ClientTableRow from '@/components/ClientTableRow';
import { useEffect, useState } from 'react';
export default function Home() { // We cannot use async now, so I removed it
const [selectedFilter, setSelectedFilter] = useState(); // no clue how filter looks like
const [data, setData] = useState({});
useEffect(() => {
async function loadData() {
const [rows] = await connection.query('SELECT * FROM clients');
const data = rows.map(row => ({
...row,
created_at: format(new Date(row.created_at), 'dd-MM-yyyy HH:mm:ss'),
}));
setData(data);
}
loadData(); // We're invoking this async method in a useEffect callback, which triggers a re-rendering when data gets changed
}, [/* We load the data once, when rendering the first time */ ]);
return (
<table className="min-w-full divide-y divide-gray-300">
<thead className="bg-gray-50">
<tr>
{/*filter should be here*/}
{/* TODO: add some kind of button logic here, which on click invokes setSelectedFilter with the clicked filter*/}
<td>ID</td>
<td>Name</td>
<td>Last name</td>
<td>Phone</td>
<td>Email</td>
<td>Created at</td>
<td></td>
</tr>
</thead>
<tbody className="divide-y divide-gray-200 bg-white">
{data.filter(d => true /*TODO check whether d matches the selectedFilter*/).map((item, index) => (
<ClientTableRow key={index} client={item} />
))}
</tbody>
</table>
)
};