Reputation: 691
I have the following situation. I am fetching data from the backend and the response is a bunch of objects. I want to iterate into them and in every iteration, I want to push them into my state.
here is how I am getting data from the backend:
const allBookings = useSelector(getBookings);
useEffect(() => {
dispatch(
fetchBookings.request({
getAll: true,
})
);
}, [dispatch]);
here is my data:
bookings:{
0:{id: 294, address: '1585 Charleston Rd, Mountain View, CA, USA', broker:{name:'aaa'}},
1:{id: 294, address: '1586 Charleston Rd, Mountain View, CA, USA', broker:{name:'bbb'}},
2:{id: 294, address: '1587 Charleston Rd, Mountain View, CA, USA', broker:{name:'ccc'}}
}
Here where I am trying to set my data in an array, but something goes wrong, please help me to figure out how I can achieve. The final result should be like this:
[
{id: 294, address: '1585 Charleston Rd, Mountain View, CA, USA', broker:{name:'aaa'}},
{id: 294, address: '1586 Charleston Rd, Mountain View, CA, USA', broker:{name:'bbb'}},
{id: 294, address: '1587 Charleston Rd, Mountain View, CA, USA', broker:{name:'ccc'}}
]
if (!allBookings) return null;
const book = allBookings.bookings;
const [books, setBooks] = useState([]);
useEffect(() => {
if (book) {
const x = Object.entries(book);
setBooks(x);
}
}, [book]);
console.log('books===>', books);
Upvotes: 3
Views: 15424
Reputation: 14702
In your useEffect
use the store selector var to watch changes ,
also you shouldn't use Object.entries in your case , instead use Object.values ,
Object.entries will get both key and values , and put them as an array for each entry like
[["0",{id: 294, address: '1585 Charleston Rd,...}]]
but Object.values
wil only create new array from values ( your objects )
your code should looks like
const [books, setBooks] = useState([]);
useEffect(() => {
if (allBookings.bookings) {
const entries = Object.values(allBookings.bookings);
setBooks(entries);
}
}, [allBookings]);
Try the below Snippet :
// Get a hook function
const {useState, useEffect } = React;
const Example = ({title}) => {
let serverObject = {
bookings:{
0:{id: 294, address: '1585 Charleston Rd, Mountain View, CA, USA', broker:{name:'aaa'}},
1:{id: 294, address: '1586 Charleston Rd, Mountain View, CA, USA', broker:{name:'bbb'}},
2:{id: 294, address: '1587 Charleston Rd, Mountain View, CA, USA', broker:{name:'ccc'}}
}
}
const [allBookings, setAllBookings] = useState({});
const [books, setBooks] = useState([]);
setTimeout(()=> { setAllBookings(serverObject)}, 2000)
useEffect(() => {
if (allBookings.bookings) {
const entries = Object.values(allBookings.bookings);
setBooks(entries);
}
}, [allBookings]);
return (
<div>
{
books.map( book => <p> {book.address} </p>)
}
</div>
);
};
// Render it
ReactDOM.render(
<Example title="Example using Hooks:" />,
document.getElementById("app")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
<div id="app"></div>
Upvotes: 1
Reputation: 376
Never recommended to mutate the state directly.
The recommended approach in later React versions is to use an updater function when modifying states to prevent race conditions:
For Functional Components
const [array,setArray] = useState([]);
Push value at the end:
setArray(oldArray => [...oldArray,newValue] );
Push value at the beginning:
setArray(oldArray => [newValue,...oldArray] );
For Class Components
Push string to end of the array, you do this...
this.setState(prevState => ({
myArray: [...prevState.myArray, "new value"]
}))
Push string to beginning of the array, you do it like this ...
this.setState(prevState => ({
myArray: ["new value", ...prevState.myArray]
}))
Push object to end of the array, you do this ...
this.setState(prevState => ({
myArray: [...prevState.myArray, {"name": "object"}]
}))
Push object to beginning of the array, you do this ....
this.setState(prevState => ({
myArray: [ {"name": "object"}, ...prevState.myArray]
}))
Upvotes: 0
Reputation: 10071
use Object.values
instead of Object.entries
.
Also, merge new res with the previous res.
const data = Object.entries(book);
setBooks(books => [...books, ...data]);
Upvotes: 0
Reputation: 886
change const x = Object.entries(book)
; to const x = Object.values(book);
Upvotes: 1
Reputation: 66103
Use functional update to push new entires into your books
array:
const x = Object.entries(book);
setBooks(books => [...books, ...x]);
Since you’re always instantiating with an empty array you also don’t need the falsy check, ie you can remove if (books)
.
Upvotes: 2