Next.js Discord

Discord Forum

How do I trigger a re render of my current page from the navbar?

Unanswered
Blanc de Hotot posted this in #help-forum
Open in Discord
Blanc de HototOP
Home page ('/')
import styles from "./page.module.css";
import FileComponent from "@/components/FileComponent";

const files = [
    {
        name: "app.pdf",
        size: 10,
        unit: "KB",
        id: "1"
    },
    {
        name: "abc.txt",
        size: 5,
        unit: "KB",
        id: "2"
    },
]

export default function Home() {
  return (
      <main className={styles.main}>
          {files.map((file) => (
              <FileComponent name={file.name} size={file.size} unit={file.unit} key={file.id}/>
        ))}
      </main>

  );
}


layout.tsx
import type { Metadata } from "next";
import { Google_Sans } from "next/font/google";

import "./globals.css";
import { config } from '@fortawesome/fontawesome-svg-core'
import type React from "react";
import Navbar from "@/components/Navbar";
import '@fortawesome/fontawesome-svg-core/styles.css'
config.autoAddCss = false

const googleSans = Google_Sans({
  variable: "--font-google-sans",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "VinnoDrive",
  description: "A streamlined, next-generation file storage platform.",
};



export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={`${googleSans.variable}`}>
        <Navbar/>
        {children}
      </body>
    </html>
  );
}


I have a button in the navbar that opens the file broswer to select files
I want to trigger a re render of my home page to include the new files once I've uploaded them , how do I do that?

14 Replies

Blanc de HototOP
If there's a way to send the list of files selected from the button in the navbar to the page, that would be great too, so that I can just add the new files without having to iterate through the entire filesystem
@Blanc de Hotot If there's a way to send the list of files selected from the button in the navbar to the page, that would be great too, so that I can just add the new files without having to iterate through the entire filesystem
Greater Shearwater
When a file is selected what happens? Do you submit them to a database? If so, you can call revalidatePath("/") in your server actions (assuming you are using server actions). That will cause the route to re fetch the data and re render the UI with the new file.
https://nextjs.org/docs/app/api-reference/functions/revalidatePath

Or are you not submitting to a server but rather keeping the file on the client? Then you would need the files to be in React state. When the file is selected you update the state with the new file and the UI is re rendered as a result of state change.
Blanc de HototOP
Navbar.tsx
'use server';


/*ADDED NEWLY*/
async function reVal(path: string) {
    'use server';
    revalidatePath(path);
}

export default async function Navbar() {

    let usedSize = 2;
    let usedUnit = "MB"
    return (
        <nav>
            <Link href="/">
            <div>
                <Image src={'/logo.png'} alt={""} width={32} height={32} />
                <h2 id={"title"}>VinnoDrive</h2>
            </div>
            </Link>


            <NavButton reval={reVal}/> // passing fn as prop

            <Link className={"routes"} href="/">My Drive</Link>
            <Link className={"routes"} href="/bin">Bin</Link>

            <div id="progressbar">
                <div></div>
            </div>
            <p className={"storage"}>{usedSize} {usedUnit} of 10 MB used</p>
        </nav>
    );
}


NavButton.tsx
'use client';

import {useRef, useState} from "react";



export default function NavButton(props) {
    const [dropdown, setDropdown] = useState(false);

    const inputRef = useRef(null);

    const handleFileChange = (event) => {
        const files = event.target?.files;
        if (files.length > 0) {
         console.log('Selected file:', files.name);
         props.reval(usePathname());
        }
    };

    return (
       <div className="dropdown">
                <input name="File upload" type="file" ref={inputRef} onChange={handleFileChange}/>
                <button type="button" onClick={ () => setDropdown(!dropdown) } value={"+ New"}>+ New</button>
                <div id="myDropdown" className={`dropdown-content${dropdown ? " show": ""}` }>
                    <div id={"new_folder"} className={"element"}>New folder</div>
                    <div id={"file_upload"} className={"element"} onClick={() => inputRef.current?.click()}>File upload</div>
                    <div className={"element"}>Folder upload</div>
                </div>
            </div>
    );
}
trying to call the fn in the client component I get the error
## Error Type
Runtime Error

## Error Message
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.


    at handleFileChange (file://C:/Users/TechPro424/Documents/GitHub/vinnodrive/.next/dev/static/chunks/src_components_NavButton_tsx_133bc68b._.js:29:206)
    at input (<anonymous>:null:null)
    at NavButton (file://C:/Users/TechPro424/Documents/GitHub/vinnodrive/.next/dev/static/chunks/src_components_NavButton_tsx_133bc68b._.js:39:215)
    at Navbar (src\components\Navbar.tsx:27:13)
    at RootLayout (src\app\layout.tsx:31:9)

## Code Frame
  25 |
  26 |
> 27 |             <NavButton reval={reVal}/>
     |             ^
  28 |
  29 |             <Link className={"routes"} href="/">My Drive</Link>
  30 |             <Link className={"routes"} href="/bin">Bin</Link>

Next.js version: 16.1.1 (Turbopack)
@Greater Shearwater
Greater Shearwater
Yeah, you can call React hooks only at the top of a component function. Not conditionally or inside other functions like you are doing here.
props.reval(usePathname());
Blanc de HototOP
Ahh
there is no equivalent for usePathname in a server component afaik, any alternative methods?
Blanc de HototOP
@Greater Shearwater
Greater Shearwater
If the path is dynamic you can get the route segment using the params prop in the page or layout server components.

But if they are not dynamic I don't think there is a way you can access them inside the server component. Then again if they are not dynamic you can usually hardcode the pathname inside your revalidatePath().
What are you trying to do though? In your server action there is only a revalidatePath(), but I don't see any other code creating or updating any data in a database. Unless you have omitted them when sharing the code. Usually you call revalidatePath() after updating your database.

If you don't store those files in a database or some other storage, and only keeping them on the client, what you need is React state. revalidatePath() won't help you there.
Blanc de HototOP
The files array in the home page is a placeholder, ill add the actual functionality later

But what I want to do is upload the file to the backend which then puts it in storage, and update the file list to reflect the nee files

This will also happen inside a /folders/[id]/ path later, it depends on which directory is currently open, so I can't hardcode the path in the navbar
In the folders case, I could use the params prop, but that wouldn't work for the root directory
@Greater Shearwater
Greater Shearwater
Ah ok. I guess I'd just revalidate everything in this case. revalidatePath('/', 'layout'). So it won't matter where you call the file uploader from.

If you are using Next.js 16 and cache components, you can give a cache tag to the function that fetches the files. Then inside the server action you can call revalidateTag("your-tag"). I think that should work too, depending on whether you are using cache components or not. https://nextjs.org/docs/app/api-reference/functions/cacheTag
https://nextjs.org/docs/app/api-reference/functions/revalidateTag