How to add key property to list mapping

My app displays list of names of users, when a user clicks on a name it should open a new page with users full details. But when the link is clicked it opens the page without
displaying users details.

I know the challenge is adding key property to the Link from react-router-dom but i can
seem to implement it. See the code below

import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";

const User = () => {
  const [error, setError] = useState(null);
  const [isLoaded, setIsLoaded] = useState(false);
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users/")
      .then((res) => res.json())
      .then(
        (data) => {
          setIsLoaded(true);
          setUsers(data);
        },
        (error) => {
          setIsLoaded(true);
          setError(error);
        }
      );
  }, []);
  if (error) {
    return <div>Error: {error.message}</div>;
  } else if (!isLoaded) {
    return <div>Loading...</div>;
  } else {
    return (
      <ul>
        {users.map((user) => (
          <li key={user.id}>
            <Link to={`user/${user.id}`}>{user.name}</Link>
          </li>
        ))}
      </ul>
    );
  }
};
export default User;
import React, { useState, useEffect } from "react";

const UserDetail = (props) => {
  var id = props.match.params.id;
  const [error, setError] = useState(null);
  const [isLoaded, setIsLoaded] = useState(false);
  const [user, setUser] = useState([]);
  const [userAddress, setUserAddress] = useState([]);
  const [userCompany, setUserCompany] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users/" + id)
      .then((res) => res.json())
      .then(
        (data) => {
          console.log(data);
          setIsLoaded(true);
          setUser(data);
          setUserAddress(data.address);
          setUserCompany(data.company);
        },
        (error) => {
          setIsLoaded(true);
          setError(error);
        }
      );
  }, []);
  if (error) {
    return <div>Error: {error.message}</div>;
  }
  if (!isLoaded) {
    return <div>Loading...</div>;
  }

  if (user) {
    return (
      <div>
        <h1>{user.name}</h1>
        <div>Email: {user.email}</div>
        <div>Phone: {user.phone}</div>
        <div>Website: {user.website}</div>
        <div>Company: {userCompany.name}</div>
        <div>
          Address: {userAddress.street}, {userAddress.suite}, {userAddress.city}
          , {userAddress.zipcode}
        </div>
      </div>
    );
  }
};
export default UserDetail;

Kindly look through the code and profer a solution

Thank you

Hi,
Is this a private project you’d like to keep secret? If not would you mind pushing it to a git repo so we could clone it to run locally ? It is difficult to statically find the error.
Last time I copy pasted it and made it work but that is tedious.

As the React course teaches use the dev tools and extensions that help troubleshoot the problem.

  • Use React Dev Tools to check the states.
  • Check any message in the console.
  • Check any failing requests in the Network tab.

Also why using Fetch when the course taught to use Axios and write an httpService that makes its use clean and easy?

Last thing would be using an object instead of separate states.
Unlike with class components you’ll need to be careful when updating one property.
In class components this.setState({oneProperty: newValue}) would just update the oneProperty property and that’s convenient.
In functional components and useState you’d declare an object like

const [user, setUser] = useState({});

similarly to what you did (bur with curlyy braces instead of square brackets)

const [user, setUser] = useState([]);

Then to update one or several properties in a greater set you’d use the spread operator.

setUser({...user, oneProperty: newValue});

I just found you can also use reducer and custom hooks thanks to this SO post.

Hi UniqueNoSpaceShot thank you for the help