Reputation: 514
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
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
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