I am quite new to useParams
and ExpressJS and am trying to use it to display a detailed user profile after clicking on a list of profiles tagged with their profile number. The user profiles are an object stored in an array. I am trying to get the link in the browser to display it as "https://localhost/3000/profile/1" where 1 is the index number instead of the profile number like "https://localhost/3000/profile/A123".
Data is being stored in profile.json: [{"PROFILE_NUMBER": "A123", "NAME": "X", "AGE" : "21", "HOBBY" : "RUN"} , .....]
In the utils.js
const getProfiles = async () => {
// Retrieve sightings.json file contents as string
const profiles = await readFile("./profiles.json", "utf8");
// Return sightings as an object
return JSON.parse(profiles);
};
module.exports = {
getProfiles
}
Here is my index.js in my backend folder
const express = require("express");
const { getProfile } = require("./utils.js");
var cors = require("cors");
require("dotenv").config();
const PORT = process.env.PORT;
const app = express();
app.use(cors());
app.get("/profiles", async (req, res) => {
const profiles = await getProfile();
res.json(profiles);
});
app.get("/profiles/:profileIndex", async (req, res) => {
const profiles = await getProfile();
res.json(profiles[req.params.profileIndex]);
});
app.listen(PORT, () => {
console.log(`Express app listening on port ${PORT}!`);
});
On the other hand, for my frontend. This is my App.js where the data is being called from the backend:
import React from "react";
import "./App.css";
import Card from "./Card";
import Single from "./Single";
import { Routes, Route } from "react-router-dom";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
profiles: [],
};
}
componentDidMount() {
fetch("http://localhost:3000/profiles")
.then((response) => response.json())
.then((data) => {
this.setState({ profiles: data });
});
}
render() {
return (
<div className="App">
<Routes>
<Route
exact
path="/profile"
element={<Card profiles={this.state.profiles} />}
></Route>
<Route
path="/profiles/:profileIndex"
element={<Single profiles={this.state.profiles} />}
></Route>
</Routes>
</div>
);
}
}
export default App;
This is my Card.js which is the list of user profiles displayed.
import React from "react";
import "./App.css";
import { Link } from "react-router-dom";
const Card = ({ profiles }) => {
return (
<div className="App">
{profiles.map((profile) => (
<div className="container">
<Link
style={{ display: "block", margin: "1rem 0" }}
to={`/profiles/${profile.PROFILE_NUMBER}`}
key={profile.PROFILE_NUMBER}
>
<div>
{profile.PROFILE_NUMBER}
<br />
{profile.NAME}
<br />
</div>
</Link>
</div>
))}
</div>
);
};
export default Card;
Lastly, this is the Single.js where it display individual profile
import React from "react";
import { useParams } from "react-router-dom";
import "./App.css";
const Single = ({ profiles }) => {
let params = useParams();
var newArray = profiles.filter(function (el) {
return el.PROFILE_NUMBER === params.profileIndex;
});
return (
<div className="App">
{console.log(newArray)}
{`Report Number: ${newArray[0].PROFILE_NUMBER}`}
<br />
{`County: ${newArray[0].NAME}`}
<br />
{`Year: ${newArray[0].AGE}`}
<br />
{`Description: ${newArray[0].HOBBY}`}
</div>
);
};
export default Single;
How do I get the link to display index number and show the correct user profile instead of using the profile number? Any guidance on how to implement a search function too? Thank you!
CodePudding user response:
If you want the profileIndex
route path param to be the profiles array index instead of the specific profile number of an element in the array then pass the mapped index in the link and use the profileIndex
param as the array index when pulling a profile object from the array.
Example:
const Card = ({ profiles }) => {
return (
<div className="App">
{profiles.map((profile, index) => (
<div className="container">
<Link
style={{ display: "block", margin: "1rem 0" }}
to={`/profiles/${index}`} // <-- pass array index here
key={profile.PROFILE_NUMBER}
>
<div>
{profile.PROFILE_NUMBER}
<br />
{profile.NAME}
<br />
</div>
</Link>
</div>
))}
</div>
);
};
...
const Single = ({ profiles }) => {
const { profileIndex } = useParams();
const profile = profiles[profileIndex];
if (!profile) {
return "No Profile";
}
return (
<div className="App">
{`Report Number: ${profile.PROFILE_NUMBER}`}
<br />
{`County: ${profile.NAME}`}
<br />
{`Year: ${profile.AGE}`}
<br />
{`Description: ${profile.HOBBY}`}
</div>
);
};