how to loop through two array in react? - reactjs

I'm trying to get my data from 2 arrays:
Here is my function:
function Cart({ basketProps }) {
let productsInCart = [];
Object.keys(basketProps.products).forEach(function (item) {
if (basketProps.inCart) {
productsInCart.push(basketProps.products);
}
console.log(productsInCart);
});
...
...
...
}
when i do console.log it return me this:
[{…}]
0:
products: Array(1)
0:
img_url1: "https://thebeuter.com/wp-content/uploads/2020/06/38-1.jpg"
price: 1290000
title: "BEUTER BACK2BACK ZIPPER WHITE JACKET"
__proto__: Object
length: 1
__proto__: Array(0)
__proto__: Object
length: 1
__proto__: Array(0)
How can I use .map to loop thru these?
Updated:
When I do console.log(basketProps). It gave me this:
basketNumbers: 1
cartCost: 1290000
inCart: true
numbers: 1
products:
products: Array(1)
0: {title: "BEUTER BACK2BACK ZIPPER WHITE JACKET", price: 1290...}

You dont require the 'Object.keys' function, since inCart is already available at outer level.
if (basketProps.inCart) {
productsInCart.push(basketProps.products);
}
let total =0;
productsInCart.map(cartProduct=>{
total = total + cartProduct.price;
}
You can run the map function on productInCart array like above.

To select all products inCart use:
filter to select all products inCart
map (or flatMap) to select products property you're interested in
I use flatMap because it makes list easier to render - it makes an array of products, not an array of product arrays. flatMap first maps each element using a mapping function, then flattens the result into a new array (it is identical to a map() followed by a flat() of depth 1).
function App() {
return <Cart basketProps={DATA} />;
}
function Cart({ basketProps }) {
const productsInCart = basketProps
.filter(product => product.inCart)
.flatMap(product => product.products);
return (
<div className="App">
<ul>
{productsInCart.map(product => (
<li>{product.title}</li>
))}
</ul>
</div>
);
}
const DATA = [
{ inCart: true, products: [
{ title: "PRODUCT 1", price: 10 },
{ title: "PRODUCT 2", price: 20 }
]},
{ inCart: false, products: [
{ title: "PRODUCT 3", price: 30 },
{ title: "PRODUCT 4", price: 40 }
]},
{ inCart: true, products: [
{ title: "PRODUCT 5", price: 50 },
{ title: "PRODUCT 6", price: 60 }
]}
];
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

I assume basketProps.products is an object array which has list of products, and has inCart = true if the product is in cart
In that case your code to get the products in cart should be like this
let productsInCart = [];
if(basketProps && Array.isArray(basketProps.products)) {
productsInCart = basketProps.products.filter(function (item) {
return item.inCart ;
});
}
console.log(productsInCart )
or if you are using arrow functions, the one liner would be (add array validation as in example above)
let productsInCart = basketProps.products.filter((item)=>(item.inCart));
console.log(productsInCart);

Related

array.forEach is displayed on console.log but not display on screen

const brands = [
{
id: 100,
brand: "Digital Symphony",
type: "Professional Services",
projects: [
{
id: 1,
name: "project 1"
},
{
id: 2,
name: "project 2"
}
]
},
{
id: 101,
brand: "Chiqui Don",
type: "Food & Drinks",
projects: [
{
id: 4,
name: "project 4"
},
{
id: 5,
name: "project 5"
}
]
}
];
function findParentsProject(brands, id, parent = null) {
for(let brand of brands){
const result = brand.id === id ? parent
: brand.projects && findParentsProject(brand.projects, id, brand);
if (result)
{
return (Object.values(result.projects)).forEach((project, id) =>{
return(
//console.log(project.id)
<p key={id}>{project.id}</p>
)
})
//return <p>aisyah</p>
}
}
}
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div>{findParentsProject(brands, 4)}</div>
</div>
);
}
this function is to find the parents project id. the result is in object then i convert to array. then i use forEach to loop through the array. why when i try to display the result it wont display on screen. but using console.log is working fine. this is my sandbox for code reference.

How to insert map data to an array of object

I am mapping out item values which is an array
const mappedItems = items.map(item => {
return (
<div key={item.id}>
<h2>{item.name}</h2>
<h2>{item.quantity}</h2>
</div>
)
});
What get outputted is like this:
Fun Mix
1
Potato Chips
5
I am trying to insert the items to my DB from my API, and the structure of the fields is like this:
Items: {
name: //Since the mapped value of the name is an array how can I store all the mapped names in this name field which is an object
quantity: //Same for quantity
},
In my backend controller, I am getting the value like this:
const order = new Order({
Items: req.body.Items,
});
My DB structure where the items are being inserted to is like this
Items: [
{
name: { type: String, required: true },
quantity: { type: Number, default: },
}
]
You could do like this (unless I missunderstood what you are trying to do):
const backendItems = items.map(item => {name:item.name, quantity: item.quantity})
So in the end, backendItems looks like this with your example:
backendItems: [
{
name: "Fun mix",
quantity: 1,
},
{
name: "Potato Chips",
quantity: 5,
}
]

Delete an object inside an object reactjs redux?

I am building a simple application with reactjs, redux; The database like this
const initialState = [
{
title: "List 1",
id: 0,
cards: [
{
id: 0,
text: "Task 1",
},
{
id: 1,
text: "Task 2",
},
],
},
{
title: "List 2",
id: 1,
cards: [
{
id: 0,
text: "Task 3",
},
{
id: 1,
text: "Task 4",
},
],
},
];
The app has many lists. In many list has many cards, I want delete a card in a list
So in my listReducer.js. I created a delete reducer to delete a task like this.
case CONSTANTS.DELETE_CARD: {
const { listId, id } = action.payload;
return state.map((list) => {
if (list.id === listId) {
return {
...list,
cards: list.cards.filter((card) => card.id !== id),
};
}
return list;
});
}
But It not working correctly. What I am doing wrong?
the code: https://codesandbox.io/s/github/htactive-nhaptt/crud-trello?file=/src/reducers/listReducers.js:1466-1773
The issue is not with your reducer. I looked at your codesandbox example and added a few console.log and looks like everything gets updated correctly.
The problem is in the render function of your List component in components/List.js. Because you're not passing a unique key to Card component, React doesn't know what items have changed and it only sees a change in cards list lenght. So on re-render, it renders the old list up to the new length (hope it makes sense!) See here for more info on keys: https://reactjs.org/docs/lists-and-keys.html#keys.
You can fix the issue by passing a unique key to Card like this on line 72:
return <Card key={card.id} id={card.id} listId={listId} text={card.text} />;

How to properly map results from api fetch react

I've got my fetch request setup and properly retrieving the data from the API. However, I'm receiving the 'Unhandled Rejection (TypeError): items.map is not a function' error when I try to map the results into list items. How am I meant to map out the 'titles' into deliverables?
Here's my current setup:
Output of fetch request
{1: {…}, 2: {…}, 3: {…}, 4: {…}, 6: {…}, 7: {…}, 8: {…}, 9: {…}}
1:
entries: "598"
id: "1"
title: "Newsletter SignUp"
__proto__: Object
2: {id: "2", title: "Contact Page Form", entries: "663"}
3: {id: "3", title: "Sidebar RFI", entries: "114"}
4: {id: "4", title: "White Paper Email Sign-Up", entries: "72"}
6: {id: "6", title: "White Paper Registration", entries: "84"}
7: {id: "7", title: "Services RFI", entries: "766"}
__proto__: Object
Code to fetch / render from api
componentDidMount() {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "Basic XXX");
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch("https://www.example.com/wp-json/gf/v2/forms", requestOptions)
.then(res => res.json())
.then(
(result) => {
console.log(result);
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const { error,
isLoaded,
items
} = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
<div>
{items.map(item => (
<li key={item.title}>
{item.title}
</li>
))}
</div>
</div>
);
}
}
This is a question about javascript basics, not react or apis. The question is really how to map over an object with object as values.
One way is to get the keys (like SomoKRoceS shows) is Object.keys:
Object.keys(obj).map(key => (
<li key={obj[key].title}>
{items[obj].title}
</li>
))
Another way is to "for in" :
for (const key in obj) {
if (obj.hasOwnProperty(prop)) {
list.push(<li key={obj[key].title}>{items[obj].title}</li>)
}
}
return list;
Another way is Object.values:
Object.values(obj).map(val => <li key={val.title}>{val.title}</li>)
You can do something like this:
export default class Example extends React.Component {
// Your state will look something like this after the get request
state = {
result: {
1: { id: "1", title: "Contact Page Form", entries: "663" },
2: { id: "2", title: "Contact Page Form", entries: "663" },
3: { id: "3", title: "Sidebar RFI", entries: "114" },
4: { id: "4", title: "White Paper Email Sign-Up", entries: "72" },
6: { id: "6", title: "White Paper Registration", entries: "84" },
7: { id: "7", title: "Services RFI", entries: "766" }
}
};
renderResult = () => {
const res = Object.values(this.state.result);
return res.map(item => <div>{item.title}</div>);
};
render() {
return <div>{this.renderResult()}</div>;
}
}
Live demo here: https://codesandbox.io/s/polished-river-kueyq?file=/src/App.js:51-738
map() is a method applied on arrays. You can create an array of all indexes of the object, and then map over it - for each element, get the value of that key from the original object.
So you can do something like this:
return (
<div>
<div>
{Object.keys(items).map(item => (
<li key={items[item].title}>
{items[item].title}
</li>
))}
</div>
</div>
);
Object.keys(items) will create an array of all keys in items which is [1,2,3,...], then the map will iterate over that array and you will be able to access the desired object with that key with items[item].

TypeError: posts is not iterable returning data from firebase

I'm new using react and firebase.
I try to get posts from firebase:
useEffect(() => {
setLoading(true);
setError(false);
let cancel;
// get posts
var postsRef = firebase.database().ref('/posts/');
postsRef.on('value', function(snapshot) {
setPosts(prevPosts => {
var posts = snapshot.val();
console.log(posts);
return [...prevPosts,...posts]
});
});
setLoading(false);
}, [ pageNumber ]);
The problem is it gives me:
TypeError: posts is not iterable on return [...prevPosts,...posts]
any ideas how to solve this? this will return data to a function that will parse data like this:
return (
<>
{posts.map((post, index) => {
return <Post key={post.id} id={post.id} ref={ref} img={post.img} titulo={post.titulo} />
})}
</>
)
Why I get this error? how can I parse my data correctly?
thanks!
Since your post variable is an object like:
{
"-M5GmoelPzWryNizVjww": { img: "img/", titulo: "title 1", user: "root" },
"-M5GmsTDcbDYZuoYBVIt": { img: "img/", titulo: "title 2", user: "root" },
"-M5GmxMZMzZe9p5uDuWe": { img: "img/", titulo: "title 3", user: "root" },
"-M5GmyKDbbtxR8Dw3-J2": { img: "img/", titulo: "title 4", user: "root" },
"-M5GmzHjK1PQJ2ulrCTi": { img: "img/", titulo: "title 5", user: "root" },
"-M5Gn2Rsv_OrwL1GkbVG": { img: "img/", titulo: "title 6", user: "user" },
"-M5Gn39y9JDishOdxwi4": { img: "img/", titulo: "title 7", user: "user" }
}
You should transform it previously to an array so that you can concatenate it to your previous list of posts. To do so, and using the key of the object as an id, you can use:
return [...prevPosts, ...Object.keys(posts).map(key => ({
id: key,
...posts[key]
}))];

Resources