Julie
Julie

Reputation: 514

error getting specific data from data base via id

I need to render balance and employee data to the user via axios.get using the specific post id from useParams hook. I tried to render the data in the JSX without mapping and got the following error:

Error: Objects are not valid as a React child (found: object with keys {message, data}). If you meant to render a collection of children, use an array instead.

I don't think I need to map the data, but I tried it and got this error:

TypeError: balance.map is not a function

Neither seems to work. I am sure this a simple fix but I can't seem to figure it out. I consoled res. data and printing the data just fine:

{message: "Post found", data: {…}}
data:
balance: 5
company: "ABC"
date: "2021-07-14T23:52:29.896Z"
employee: "Jane Hines"
fee: false
notes: ""
tax: false
__v: 0
_id: "60daac85f9243d290489eac1"
__proto__: Object
message: "Post found"
__proto__: Object

, so I know it's the JSX that is the issue. What did I do wrong?

Here is what I want the component to say: Jane Doe's new balance is 3.00

attempt 1 without map

import  { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";

const Success = () => {
    const [balance, setBalance] = useState("");
    const [employee, setEmployee] = useState("");
    const [notes, setNotes] = useState("");
    const { id } = useParams();

    useEffect(() => {
        axios
        .get(`http://localhost:5000/get-snapshot-id/${id}`)
        .then((res) => {
            console.log(res.data);
            setBalance(res.data);
            setEmployee(res.data);
            setNotes(res.data);
        })
        .catch((err) => {
            console.log(err);
        });

    }, [setBalance, setEmployee, setNotes]);

    return(
    <>
    <h2>Successfully Updated Balance!</h2>
    <h4> {employee}'s new balance is {balance}</h4>

    <button><a href="/search-comp-details">Continue seraching</a></button>
    <button><a href="/main">Back to Main</a></button>
    </>
    )
}
export default Success;

attempt 2 with map

import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";

const Success = () => {
  const [balance, setBalance] = useState([]);
  // const [employee, setEmployee] = useState("");
  // const [notes, setNotes] = useState("");
//   const [data, setData] = useState([]);
  const { id } = useParams();

  useEffect(() => {
    axios
      .get(`http://localhost:5000/get-snapshot-id/${id}`)
      .then((res) => {
        // setData(res.data);
        console.log(res.data);
        setBalance(res.data);
        // setEmployee(res.data);
        // setNotes(res.data);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  return (
    <>
      <h2>Successfully Updated Balance!</h2>
      {balance.map((d) => (
        <h4 key={d.id}>
          {d.employee}'s new balance is {d.balance}
        </h4>
      ))}

      <button>
        <a href="/search-comp-details">Continue seraching</a>
      </button>
      <button>
        <a href="/main">Back to Main</a>
      </button>
    </>
  );
};
export default Success;

Upvotes: 1

Views: 51

Answers (2)

Julie
Julie

Reputation: 514

I figured it out, I needed to call the data object with in the data object: instead of console.log(res.data) i needed console.log(res.data.data), so to get the balance data i needed : setBalance(res.data.data.balance)

It wasn't the JSX that was the issue it was the Axios req.

Upvotes: 1

Drew Reese
Drew Reese

Reputation: 202676

With a res.data response object:

{message: "Post found", data: {…}}

data:
  balance: 5
  company: "ABC"
  date: "2021-07-14T23:52:29.896Z"
  employee: "Jane Hines"
  fee: false
  notes: ""
  tax: false

it seems you want the balance and employee properties from the nested data property, i.e. res.data.data.balance.

You can either save the entire res.data object and reference into the nested keys. Remember to use valid initial state of the same type and conditionally render the result when available.

const Success = () => {
  const [data, setData] = useState({}); // <-- object type
  const { id } = useParams();

  useEffect(() => {
    axios
      .get(`http://localhost:5000/get-snapshot-id/${id}`)
      .then((res) => {
        setData(res.data.data);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  if (!data.employee && !data.balance) {
    return <div>Loading...</div>;
  }

  return (
    <>
      <h2>Successfully Updated Balance!</h2>
      <h4 key={d.id}>
        {data.employee}'s new balance is {data.balance}
      </h4>

      <button>
        <a href="/search-comp-details">Continue searching</a>
      </button>
      <button>
        <a href="/main">Back to Main</a>
      </button>
    </>
  );
};

Or save the nested state individually and do the same as above.

const Success = () => {
  const [balance, setBalance] = useState('');
  const [employee, setEmployee] = useState("");
  const { id } = useParams();

  useEffect(() => {
    axios
      .get(`http://localhost:5000/get-snapshot-id/${id}`)
      .then((res) => {
        setBalance(res.data.data.balance); // <-- get nested values
        setEmployee(res.data.data.employee);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  if (!employee && !balance) {
    return <div>Loading...</div>;
  }

  return (
    <>
      <h2>Successfully Updated Balance!</h2>
      <h4 key={d.id}>
        {employee}'s new balance is {balance}
      </h4>

      <button>
        <a href="/search-comp-details">Continue searching</a>
      </button>
      <button>
        <a href="/main">Back to Main</a>
      </button>
    </>
  );
};

Upvotes: 1

Related Questions