skip to Main Content

I have some code in a MERN stack app where users can enter another user’s name into a search bar, and the webpage will return other properties of the user whose name they searched up.

For example, if I search up "John Doe" in the search bar, it should return something like this in the front end:

Name: John Doe
Age: 30
Sex: Male

Here is the code for the React component I made to handle this:

import React, { useState, useEffect } from "react";
import axios from "axios";
import "../../styles/styles.css";

function SearchUser() {
  const [user, setUser] = useState({});
  const [searchQuery, setSearchQuery] = useState("");
  const [formError, setFormError] = useState(false);

  async function getUsers(query) {
    const response = await axios.get(`http://localhost:5000/auth/userSearch?fullName=${query}`);
    setUser(response.data);
  }

  const handleSubmit = async (e) => {
    e.preventDefault();

    if (!searchQuery) {
      setFormError(true);
      return;
    }

    setFormError(false);
    getUsers(searchQuery);
  };

  useEffect(() => {
    console.log(user);
  }, [user]);

  return (
    <div className="container">
      <div className="create-profile-border">
        <h1>Search a user</h1>
        <form onSubmit={handleSubmit}>
          <div>
            <input
              type="text"
              placeholder="Enter a user's full name here"
              onChange={(e) => {
                setSearchQuery(e.target.value);
              }}
              value={searchQuery}
            />
            {formError && !searchQuery && (
              <p className="error-message">This is a required field</p>
            )}
          </div>
          <button className="create-profile-button" type="submit">
            Search
          </button>
        </form>

        {user.fullName > 0 && (
          <div>
            <p>Name: {user.fullName}</p>
            <p>Age: {user.age}</p>
            <p>Sex: {user.sex}</p>
          </div>
        )}
      </div>
    </div>
  );
}


export default SearchUser;

I have checked and confirmed that the backend code is working properly, the issue purely lies in the frontend.

The Issue I have:

After debugging and some console logging, it seems that user.fullName/user.age/user.email are all undefined. However, in this console log:

useEffect(() => {
    console.log("effect[user]:", JSON.stringify(user));
  }, [user]);

I get back a user object in the browser console when I type "John Doe" in the search bar:

effect[user]: {"user":{"_id":"63eea67c0316be96ebf799f0","email":"[email protected]","passwordHash":"DU7fwnIlucrwT7R","fullName":"John Doe","age":"30","sex":"male","__v":0}}

I suspect there’s some funny business with the rendering but as I’m still inexperienced with React, I’m not sure where to go from here. Any help would be greatly appreciated.

3

Answers


  1. Your main issue is trying to compare the string property user.fullName to numeric 0. Unless your string is purely numeric, user.fullName > 0 will always be false.

    Instead of initialising user to be an empty object, try starting it with null. Then you can more easily test if it has a value or not…

    const [user, setUser] = useState(null);
    
    // ...
    
    {user && (
      <div>
        <p>Name: {user.fullName}</p>
        <p>Age: {user.age}</p>
        <p>Sex: {user.sex}</p>
      </div>
    )}
    

    Another improvement you can make is to employ Axios’ params option to correctly encode URL query parameters.

    Update: after prompting you to debug your own API response, it also seems your response data is nested under a user property

    const getUsers = async (fullName) => {
      setUser(
        (
          await axios.get("/auth/userSearch", {
            baseURL: "http://localhost:5000/", // even better, use your .env file
            params: { fullName },
          })
        ).data.user // 👈 extract the `user` property
      );
    };
    

    Edit compassionate-gwen-ztvy8x

    Login or Signup to reply.
  2. I subscribe to all the suggestions from phil. However, after looking at the log from your console, I think your data is returned as a user. so you should be able to get the data by setting user to response.data.user

    async function getUsers(query) {
        const response = await axios.get(`http://localhost:5000/auth/userSearch?fullName=${query}`);
        setUser(response.data.user);
      }
    

    or

    const getUsers = async (fullName) => {
      setUser(
        (
          await axios.get("/auth/userSearch", {
            baseURL: "http://localhost:5000/", // even better, use your .env file
            params: { fullName },
          })
        ).data.user
      );
    };
    
    Login or Signup to reply.
  3. Can you share the full JSON response from your API? I’m asking because what you pasted seems to imply the response looks something like this:

    {
      user: { _id: "...", email: "...", passwordHash: "..." },
      _id: "63eea67c0316be96ebf799f0"
      fullName: "John Doe"
    ​​  age: "30"
    }
    

    Said another way… Based on your paste, the data.user object does not contain the fullName property, but rather data.fullName does.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search