I am using nextjs, I have a page where it lists out all clients, I can then click each client name that links (using next/link) to a page specifically for that client. It loads correctly using useEffect and useState. If I refresh manually all data loads correctly. Yet If I open the "add invoice" form and submit, the submission goes through correctly to the database, yet on refresh (from clicking submit) the page loads none of the original information on the initial fetch. The page, clients.js, has a component that has a query part that sends the client id and name to the [id].js page, eventually sent to the server via the fetchInvoices function. [id].js calls clientTitle.jsx for the add invoice button that holds the form and submit button. I have been working on this site so much to prove to myself that I can actually code and create instead of just copying youtube tutorials so it would be great if I could get help thanks.
NOTE see <==== in code for important info
My debugging effort: After doing some debugging, the router.query in [id].js retains the information for the id but not for the name upon submitting, this is important as for the fetch to function correctly the individual invoices for the client to be fetched the name is needed. So why does the id stay stored but not the name from the query, is it because only the id part is in the URL link, since [id].js in react renames that to the actual Id? Thats my thinking but unsure. I am sure this is the problem.
Code layout: This is the main client page with all clients layout | FILENAME: clients.js
const clients = ({ clients }) => {
return (
<div>
<Title title="Clients" />
<div>
{clients.map((client) => (
//Maps out all the clients in the database//
<div key={client._id}>
{/* <Link href="/clientInfo"> */}
<Link
href={{
pathname: "/clients/[id]",
query: {
id: client._id, <=============================
name: client.name, <=======
},
}}
>
<div >
<a>{client.name}</a>
</div>
</Link>
<span>{client.balance}</span>
<span>{client.trips}</span>
</div>
))}
</div>
</div>
);
};
After clicking a client name it opens this page | FILENAME: [id].js //used like this so id shows up as part of URL
import ClientTitle from "./ClientTitle";
const ClientInfo = () => {
const router = useRouter();
const { id, name } = router.query; //gets slug info from url <=======================
const [clientData, setClientData] = useState({});
const [clientInvoices, setClientInvoices] = useState(null);
//fetches data sets to state
const fetchData = async () => {
const data = await axios.get(`http://localhost:5010/clients/${id}`);
setClientData(data.data);
return data;
};
const fetchInvoices = async () => {. <======================
//get client specific invoices
const invoices = await axios.get(
`http://localhost:5010/clients/${id}/fetch?client=${name}` <=====taken from top
);
console.log(id);
console.log(name);
console.log(invoices);
console.log("fetching");
setClientInvoices(invoices.data);
};
//runs at start of page and refresh dependent on router readiness
useEffect(() => {
if (router.isReady) {
fetchData();
fetchInvoices();
}
}, [router.isReady]);
return (
<div>
<ClientTitle <==============
title={clientData.name}
balance={clientData.balance}
clientId={clientData.clientId}
/>
<div>
<div>
<span>Date</span>
<span>From</span>
<span>To</span>
<span>Price</span>
</div>
{clientInvoices &&
clientInvoices.map((invoice) => (
<div key={invoice._id}>
<div>{invoice.date}</div>
<div>{invoice.from}</div>
<div>{invoice.to}</div>
<div>{invoice.price}</div>
</div>
))}
</div>
</div>
);
};
export default ClientInfo;
In the above code it calls this code below in another file, for the top nav bar with the submission form | FILENAME: ClientTitle.jsx
const Form = ({ name }) => {
const [clientInvoice, setClientInvoice] = useState({
client: name,
date: "",
from: "",
to: "",
quantity: null,
loadType: "",
price: null,
note: "",
});
const handleSubmit = async (e) => {
await axios.post("http://localhost:5010/clients/invoices", clientInvoice);
};
return (
<div className="relative">
<div>
<span>New Invoice</span>
<form onSubmit={handleSubmit}>
<input
placeholder="date"
onChange={(e) =>
setClientInvoice({ ...clientInvoice, data: e.target.value })
}
/>
<input
placeholder="from"
onChange={(e) =>
setClientInvoice({ ...clientInvoice, from: e.target.value })
}
/>
<input
placeholder="to"
onChange={(e) =>
setClientInvoice({ ...clientInvoice, to: e.target.value })
}
/>
<input
placeholder="quantity"
onChange={(e) =>
setClientInvoice({ ...clientInvoice, quantity: e.target.value })
}
/>
<input
placeholder="boxes/pallets"
onChange={(e) =>
setClientInvoice({ ...clientInvoice, loadType: e.target.value })
}
/>
<input
placeholder="price"
onChange={(e) =>
setClientInvoice({ ...clientInvoice, price: e.target.value })
}
/>
<input
placeholder="note"
onChange={(e) =>
setClientInvoice({ ...clientInvoice, note: e.target.value })
}
/>
<button
type="submit"
>
Create
</button>
</form>
</div>
</div>
);
};
const ClientTitle = ({ title, balance }) => {
const [showForm, setShowForm] = useState(false);
const handleForm = () => {
setShowForm(!showForm);
};
return (
<div >
<div >
<h1 >{title}</h1>
<span ">Total Balance: {balance}</span>
<button
onClick={() => handleForm()}
>
<span >Add Invoice</span>
</button>
</div>
<div />
{showForm && <Form name={title} />}
</div>
);
};
export default ClientTitle;