Невозможно отобразить свойства объекта, когда объект кажется определенным (React)

У меня есть код в приложении стека MERN, где пользователи могут вводить имя другого пользователя в строку поиска, и веб-страница возвращает другие свойства пользователя, чье имя они искали.

Например, если я ищу «Джон Доу» в строке поиска, он должен возвращать что-то вроде этого во внешнем интерфейсе:

Name: John Doe
Age: 30
Sex: Male

Вот код компонента React, который я сделал для этого:

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.info(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;

Я проверил и подтвердил, что внутренний код работает правильно, проблема заключается исключительно во внешнем интерфейсе.

Проблема у меня есть:

После отладки и некоторого ведения журнала консоли кажется, что все user.fullName/user.age/user.email не определены. Однако в этом журнале консоли:

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

Я возвращаю пользовательский объект в консоли браузера, когда набираю «Джон Доу» в строке поиска:

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

Я подозреваю, что с рендерингом есть некоторые забавные проблемы, но, поскольку я все еще неопытен в React, я не уверен, что делать дальше. Любая помощь будет принята с благодарностью.

Что это politician: в начале вашего консольного объекта? Является ли ваш user на самом деле объектом, единственным ключом которого является politican, значением которого является нужный вам объект?

Robin Zigmond 17.02.2023 21:33

@RobinZigmond мб, я задавал этот вопрос, работая над каким-то другим проектом, поэтому мой мозг перепутал, это должен быть «пользователь», а не «политик».

God's Drunkest Driver 17.02.2023 21:35

Отредактировал пост соответственно, чтобы исправить опечатку

God's Drunkest Driver 17.02.2023 21:36

Хорошо, но если вывод вашей консоли таков, что вам нужно, например, user.user.email, а не user.email

Robin Zigmond 18.02.2023 00:44

У вас есть politician.fullName, хотя он нигде не объявлен, разве вы не должны использовать user там? Или я что-то упускаю

Fcmam5 20.02.2023 01:58

@Phil Я опечатался в коде - отредактировал его соответствующим образом. Та же проблема сохраняется с user.fullName > 0

God's Drunkest Driver 20.02.2023 02:24

@ Fcmam5 Ничего не пропустил, это была опечатка с моей стороны - в моем фактическом коде у меня это как user.fullName

God's Drunkest Driver 20.02.2023 02:25
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Интервьюер: Почему &apos;[] instanceof Object&apos; возвращает &quot;true&quot;?
Интервьюер: Почему '[] instanceof Object' возвращает "true"?
Все мы знаем, что [] instanceof Array возвращает true, но почему [] instanceof Object тоже возвращает true?
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) - это древовидная структура данных, которая представляет структуру и иерархию исходного кода на языке...
1
7
92
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ваша основная проблема заключается в попытке сравнить строковое свойство user.fullName с числовым 0. Если ваша строка не является чисто числовой, user.fullName > 0 всегда будет false.

Вместо того, чтобы инициализировать user пустым объектом, попробуйте запустить его с null. Тогда вам будет легче проверить, имеет ли оно значение или нет...

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

// ...

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

Еще одно улучшение, которое вы можете сделать, — использовать опцию Axios params для правильного кодирования параметров запроса URL.

Обновление: после запроса на отладку вашего собственного ответа API также кажется, что данные вашего ответа вложены в свойство user

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
  );
};

Спасибо за советы по аксиомам. Я установил const [user, setUser] = useState(null) и заменил user.fullName > 0 просто на user. Однако проблема все еще сохраняется. Когда я console.info(user) в handleSubmit, я возвращаюсь null. Однако, когда я console.info(user) под useEffect(), я возвращаю правильный пользовательский объект. Знаете, чем это вызвано?

God's Drunkest Driver 20.02.2023 02:43

Почему вы регистрируете свои значения состояния? В этом нет необходимости, и результаты часто сбивают с толку разработчиков, плохо знакомых с React. Я бы посоветовал использовать лучшие инструменты отладки, такие как расширение браузера React Dev Tools, и это только в том случае, если вам действительно нужно выполнить какую-либо отладку.

Phil 20.02.2023 02:46

Я все еще получаю null значения для user. В чем ошибка моей логики? Имейте в виду, что я протестировал свой сервер тонну, поэтому я точно знаю, что проблема не в маршрутизаторе. При нажатии кнопки отправки запускается handleSubmit, который запускает getUsers, который, в свою очередь, устанавливает объект user на основе поискового запроса. Если мой бэкэнд возвращает правильный user при поиске, что я сделал неправильно в коде внешнего интерфейса?

God's Drunkest Driver 20.02.2023 06:54

Можете ли вы изменить свой регистратор эффектов, чтобы использовать console.info("effect[user]:", JSON.stringify(user)), как в моей ссылке CodeSandbox? Тогда отредактируйте свой вопрос с деталями

Phil 20.02.2023 07:10

Отредактировал свой пост соответственно

God's Drunkest Driver 20.02.2023 19:14

@God'sDrunkestDriver, значит, исходные данные, которые вы представили, на самом деле не соответствовали вашим данным? Разве вы не контролируете ответ API? Разве вы не должны были знать структуру данных?

Phil 20.02.2023 23:10
Ответ принят как подходящий

Я подписываюсь на все предложения от Фила. Однако, просмотрев журнал с вашей консоли, я думаю, что ваши данные возвращаются как пользователь. поэтому вы должны иметь возможность получать данные, установив пользователя в response.data.user

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

Или

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

Ага! Вы были совершенно правы, response.data.user сделал свое дело. Спасибо.

God's Drunkest Driver 20.02.2023 19:17

Можете ли вы поделиться полным ответом JSON от вашего API? Я спрашиваю, потому что то, что вы вставили, кажется, подразумевает, что ответ выглядит примерно так:

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

Другими словами... Судя по вашей вставке, объект data.user не содержит свойство fullName, а data.fullName содержит.

Я отредактировал свой пост, чтобы показать JSON.stringify(user) в журнале консоли, если это поможет.

God's Drunkest Driver 20.02.2023 19:14

Другие вопросы по теме