React function renders - subscribeToMore graph-ws - javascript

I am building a chat app and using graphQl-ws and Im having issues with a function firing multiple times. My problem is why does doSubscriptionAction fire repeatedly and how to prevent that.
component
const ChatRooms = ({ selectConvo }: SelectConvoProp) => {
const {
data: { _id },
} = auth.getUser();
const { subscribeToMore, data } = useQuery(QUERY_CONVOS);
return (
<div className="sb-convos-wrapper">
<h3 className="sb-title">Chat Rooms - {data?.convos?.length}</h3>
<Convos
convos={data?.convos}
selectConvo={selectConvo}
subscribeToConvos={() => {
subscribeToMore({
document: SUBSCRIBE_CONVOS,
variables: { _id: _id },
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
return doSubscriptionAction(prev, { subscriptionData });
},
});
}}
/>
</div>
);
};
subscribeToMoreActions function
/// this function take the subscription payload and adds it to the prev query cache
const addToPrev = (prev: any, { subscriptionData }: any) => {
const newConvo = subscriptionData.data.convo;
const updatedConvos = Object.assign(
{},
{
convos: [...prev.convos, newConvo],
}
);
return updatedConvos;
};
const removeFromPrev = (prev: any, { subscriptionData }: any) => {
const deletedConvo = subscriptionData.data.convo;
const filteredConvos = prev.convos.filter(
(convo: any) => convo._id === deletedConvo._id
);
const updatedConvos = Object.assign(
{},
{
convos: [...filteredConvos],
}
);
console.log(updatedConvos);
return updatedConvos;
};
/// this function delegates which function to use based off action
export const doSubscriptionAction = (prev: any, { subscriptionData }: any) => {
if (subscriptionData.data.convo.action === "create") {
return addToPrev(prev, { subscriptionData });
}
if (subscriptionData.data.convo.action === "delete") {
return removeFromPrev(prev, { subscriptionData });
}
};
convos component
const Convos = ({ convos, selectConvo, subscribeToConvos }: ConvosProp) => {
useEffect(() => {
subscribeToConvos();
}, [subscribeToConvos]);
const [deleteConvo] = useMutation(DELETE_CONVO, {
refetchQueries: [{ query: QUERY_CONVOS }, "Convos"],
});
const handleDelete = async (_id: string) => {
await deleteConvo({ variables: { _id } });
};
return (
<div className="sb-chat-container">
{convos?.map((convo: ConvoType, i: number) => {
return (
<div className="sb-chat-item-container" key={`chatRoom ${i}`}>
<div
className="sb-chat-content-container"
onClick={() => selectConvo(convo)}
>
<div className={"sb-chat-content-container-top"}>
<h5>{convo.roomName}</h5>
</div>
<LastMessage convo={convo} />
</div>
<button onClick={() => handleDelete(convo._id)}>X</button>
</div>
);
})}
</div>
);
};
TLDR: doSubscriptionAction fires multiple times adding multiple instances of created room to other user.

Related

graphql-ws query subscribeToMore updateQuery not firing

Im tryin to get my queries to update using the subscribeToMore function. Im getting lost on why the code is a failing to execute. so far all operations query, mutation and subscribe will work independently.
FRONTEND
export const QUERY_MESSAGES = gql`
query Messages($convoId: ID!) {
messages(convoId: $convoId) {
text
senderId
convoId
createdAt
}
}
`;
export const SUBSCRIBE_MESSAGES = gql`
subscription Messages($convoId: ID!) {
messages(convoID: $convoID) {
text
convoId
}
}
`;
const ActiveChat = ({ currentConvo, me }: any) => {
const { subscribeToMore, data } = useQuery(QUERY_MESSAGES, {
variables: {
convoId: currentConvo,
},
});
return (
<section className="chat-wrapper">
<div className="messages-container">
<Messages
messages={data.messages}
me={me}
subscribeToMessages={() => {
subscribeToMore({
document: SUBSCRIBE_MESSAGES,
variables: { convoId: currentConvo },
updateQuery: (prev, { subscriptionData }) => {
console.log("hit");
if (!subscriptionData.data) return prev;
const newFeedItem = subscriptionData.data.messages;
return Object.assign({}, prev, {
messages: [newFeedItem, ...prev.messages],
});
},
});
}}
/>
<Input currentConvo={currentConvo} />
</div>
</section>
);
};
const Messages = ({ messages, me, subscribeToMessages }: any) => {
useEffect(() => {
subscribeToMessages();
console.log("use effect ran");
});
const formatTime = (time: number) =>
new Date(time * 1000).toLocaleTimeString();
console.log(messages);
return (
messages && (
<div>
{messages.map((message: any, i: number) => {
return message.senderId === me?._id ? (
<SenderBubble
key={i}
text={message.text}
time={message.createdAt}
formatTime={formatTime}
/>
) : (
<OtherUserBubble
key={i}
text={message.text}
time={message.createdAt}
formatTime={formatTime}
/>
);
})}
</div>
)
);
};
BACKEND
const pubsub = new PubSub();
Query: {
messages: async (parent, { convoId }, context) => {
if (context.user) {
return Message.find({ convoId }).sort({ createdAt: "asc" });
}
},
},
Mutation: {
/// creates a new message using sender id and emits MESSAGE_SENT event
sendMessage: async (parent, { text, convoId }, context) => {
pubsub.publish("MESSAGE_SENT", {
message: { text, convoId },
});
return Message.create({ text, convoId, senderId: context.user._id });
},
},
Subscription: {
userActive: {
subscribe: () => pubsub.asyncIterator("ACTIVE_USERS"),
},
message: {
subscribe: withFilter(
() => pubsub.asyncIterator("MESSAGE_SENT"),
(payload, variables) => {
return payload.message.convoId === variables.convoId;
}
),
},
},
tdlr: I think subscribeToMore.updateQuery isn't firing but i don't how to debug
SOLVED: turns out I placed the wrong url and port number while building the client so the ws wasn't connecting.

React: Update a specific attribute of an array of objects

I have a rather simple requirement which is turning out to be quite complex for me. I'm developing a basic todo app with following UI:
Design
Now I need to update the array of object such that only the text of specific item should be updated. Here is my attempt but it just adds a new component on every key press:
import React, {useState} from "react";
const DynamicInput = () => {
const [todos, setTodos] = useState([])
const onAddClick = () => {
setTodos(prevState => {
return [...prevState, {id: prevState.length + 1, text: "", up: "↑", down: "↓", del: "x"}]
})
}
const onValueUpdate = (id) => (event) => {
let tempObject = todos[id]
setTodos(prevState => {
return [...prevState, {
id: id,
text: event.target.value,
up: "Up",
down: "Down",
del: "x"
}];
})
}
const onUpArrow = (event) => {
console.log("On up")
}
const onDownArrow = (event) => {
console.log("On down")
}
const onDeleteArrow = (event) => {
console.log("On delete")
}
return (
<>
<button onClick={onAddClick}>+</button>
{todos.map(todo => {
return(
<div key={todo.id}>
<input onChange={onValueUpdate(todo.id)} value={todo.text}></input>
<button onClick={onUpArrow}>{todo.up}</button>
<button onClick={onDownArrow}>{todo.down}</button>
<button onClick={onDeleteArrow}>{todo.del}</button>
</div>)
})}
</>
);
};
export default DynamicInput;
To simply solve your problem you can change your onValueUpdate() method to this :
const onValueUpdate = (id) => (event) => {
setTodos(prevState => {
let data = [...prevState];
let indexOfTodo = data.findIndex(todo => todo.id === id);
data[indexOfTodo] = {
...data[indexOfTodo],
text: event.target.value,
};
return data;
});
};

ReactJS: How do I pass multiple arrays as a prop to ChildComponent?

How to map through two arrays and send data as props to other component? I want to send data from price and gamedet as a prop to Wishlist Component.As I am new to react, suggest me if this code is not good or unclean too, thanks in advance.
This is the dumb way I send whole array to Wishlist component :
price.map((game1) => {
let temp = {
steamAppID: game1.steamAppID,
storeID: game1.storeID,
normalPrice: game1.normalPrice,
salePrice: game1.salePrice,
};
console.log("temp sale", temp.salePrice);
return tempArr1.push(temp) && tempArr2.push(temp.steamAppID));
})
This is all of WishListData component:
import React, { useEffect, useState } from "react";
import Wishlist from "./Wishlist";
import "./Wishlist.css";
import "animate.css";
import axios from "axios";
const WishlistData = () => {
const [gamedet, setGameDet] = useState([]);
const [loaded, setLoaded] = useState(false);
const [stores, setStores] = useState([]);
const [price, setPrice] = useState([]);
const [wishlist, setWishlist] = useState([]);
useEffect(() => {
setWishlist(
localStorage.getItem("Wishlist")
? JSON.parse(localStorage.getItem("Wishlist"))
: []
);
}, []);
const RemoveFromWishlist = (id) => {
let newList = wishlist.filter((game) => game.gameID !== id);
setWishlist(newList)
localStorage.setItem("Wishlist", JSON.stringify(newList));
console.log("id", [wishlist.pop(id)]);
console.log("newlist", wishlist);
setGameDet([])
};
const DET_URL = `https://api.rawg.io/api/games`;
useEffect(() => {
let isCancelled = false;
const RAWGdet = () => {
wishlist &&
wishlist.map(async (game, index) => {
const res = await axios({
url: `https://cors-anywhere.herokuapp.com/${DET_URL}/${game.gameID}?key=${process.env.REACT_APP_RAWG_KEY}`,
headers: {
"X-Requested-With": "XMLHttpRequest",
},
method: "GET",
});
if (!isCancelled) {
setGameDet((gamedet) => gamedet.concat(res.data));
}
setLoaded(true);
});
};
RAWGdet();
return () => {
isCancelled = true;
};
}, [DET_URL, wishlist]);
useEffect(() => {
let isCancelled = false;
const CSPrice = () => {
wishlist &&
wishlist.map(async (game, index) => {
const res = await axios({
url: `https://cors-anywhere.herokuapp.com/${DET_URL}/${game.slug}/stores?key=${process.env.REACT_APP_RAWG_KEY}`,
headers: {
"X-Requested-With": "XMLHttpRequest",
},
method: "GET",
});
if (!isCancelled) {
setStores((stores) => stores.concat(res.data));
}
setLoaded(true);
});
};
CSPrice();
return () => {
isCancelled = true;
};
}, [DET_URL, wishlist]);
let stm = [];
stores
.map((steam) => {
return steam.results;
})
.filter((item) => {
return item.map((id) => {
return id.store_id === 1 ? stm.push(id.url) : <>{null}</>;
});
});
let idmain = [];
stm.map((steamid) => {
return steamid.split("/").map((item) => {
return idmain.push(item);
});
});
useEffect(() => {
let isCancelled = false
wishlist.length !==0 &&
wishlist.map((game, index) => {
return (
<div key={index}>
{axios
.get(
`https://www.cheapshark.com/api/1.0/deals?storeID=1&steamAppID=${game.steamID}`
)
.then((res) => {
if (!isCancelled){
setPrice((price) => price.concat(res.data));
setLoaded(true)
}
})
.catch((err) => {
console.log("ERR", err);
})}
</div>
);
});
return () => {
isCancelled = true
}
}, [wishlist]);
let tempArr1 = [];
let tempArr2 = [];
if (loaded ) {
return (
<div className="animate__animated animate__slideInDown">
<div className="wishlist_header">
<h3>Your Wishlist</h3>
</div>
{wishlist.length !== 0 ? (
price.map((game1) => {
let temp = {
steamAppID: game1.steamAppID,
storeID: game1.storeID,
normalPrice: game1.normalPrice,
salePrice: game1.salePrice,
};
console.log("temp sale", temp.salePrice);
return tempArr1.push(temp) && tempArr2.push(temp.steamAppID));
}) &&
gamedet.map((game, index) => {
// console.log("mad2", game.name);
return (
<div id="wishlist_ctn" key={index}>
<Wishlist
// key={index}
title={game.name}
steamRatingCount={game.id}
// steamRatingPercent={game[0].steamRatingPercent}
// savings={game[0].savings}
// normalPrice={}
// salePrice={salePrice}
steamAppID={tempArr2}
data={tempArr1}
image={game.background_image}
rem={() => RemoveFromWishlist(game.id)}
/>
</div>
);
})
) : (
<div className="wishlist_header">
<h3>Add Games!!</h3>
</div>
)}
</div>
);
} else {
return (
<div className="hmm">
<div className="wishlist_header">
<h3>Your Wishlist</h3>
</div>
<div className="wishlist_header">
<h3>Loading Games</h3>
</div>
);
</div>
);
}
};
export default WishlistData;
I don't understand why you need two extra arrays since you are mapping price to populate
tempArr1, which contain a copy of its items, and tempArr2, which contains a copy of its steamAppIDs.
I think you could just pass the price array as data, and a mapped version as steamAppID:
{wishlist.length !== 0 ?
(gamedet.map((game, index) => {
<Wishlist
// key={index}
title={game.name}
steamRatingCount={game.id}
// steamRatingPercent={game[0].steamRatingPercent}
// savings={game[0].savings}
// normalPrice={}
// salePrice={salePrice}
steamAppID={price.map(item => item.steamAppID)}
data={price}
image={game.background_image}
rem={() => RemoveFromWishlist(game.id)}
/>;
</div>
);
})
) : (
<div className="wishlist_header">
<h3>Add Games!!</h3>
</div>
)}

edit notes on a Google Keep clone app with React js

I am building a clone of the Google Keep app with react js. I added all the basic functionality (expand the create area, add a note, delete it) but I can't seem to manage the edit part. Currently I am able to edit the inputs and store the values in the state, but how can I replace the initial input values for the new values that I type on the input?
This is Note component
export default function Note(props) {
const [editNote, setEditNote] = useState(false);
const [currentNote, setCurrentNote] = useState({
id: props.id,
editTitle: props.title,
editContent: props.content,
});
const handleDelete = () => {
props.deleteNote(props.id);
};
const handleEdit = () => {
setEditNote(true);
setCurrentNote((prevValue) => ({ ...prevValue }));
};
const handleInputEdit = (event) => {
const { name, value } = event.target;
setCurrentNote((prevValue) => ({
...prevValue,
[name]: value,
}));
};
const updateNote = () => {
setCurrentNote((prevValue, id) => {
if (currentNote.id === id) {
props.title = currentNote.editTitle;
props.content = currentNote.editContent;
} else {
return { ...prevValue };
}
});
setEditNote(false);
};
return (
<div>
{editNote ? (
<div className='note'>
<input
type='text'
name='edittitle'
defaultValue={currentNote.editTitle}
onChange={handleInputEdit}
className='edit-input'
/>
<textarea
name='editcontent'
defaultValue={currentNote.editContent}
row='1'
onChange={handleInputEdit}
className='edit-input'
/>
<button onClick={() => setEditNote(false)}>Cancel</button>
<button onClick={updateNote}>Save</button>
</div>
) : (
<div className='note' onDoubleClick={handleEdit}>
<h1>{props.title}</h1>
<p>{props.content}</p>
<button onClick={handleDelete}>DELETE</button>
</div>
)}
</div>
);
}
And this is the Container component where I am renderind the CreateArea and mapping the notes I create. I tried to map the notes again with the new values but it wasn't working.
export default function Container() {
const [notes, setNotes] = useState([]);
const addNote = (newNote) => {
setNotes((prevNotes) => {
return [...prevNotes, newNote];
});
};
const deleteNote = (id) => {
setNotes((prevNotes) => {
return prevNotes.filter((note, index) => {
return index !== id;
});
});
};
// const handleUpdateNote = (id, updatedNote) => {
// const updatedItem = notes.map((note, index) => {
// return index === id ? updatedNote : note;
// });
// setNotes(updatedItem);
// };
return (
<div>
<CreateArea addNote={addNote} />
{notes.map((note, index) => {
return (
<Note
key={index}
id={index}
title={note.title}
content={note.content}
deleteNote={deleteNote}
//handleUpdateNote={handleUpdateNote}
/>
);
})}
</div>
);
}
There are a couple of mistakes in your code.
The state properties are in the camel case
const [currentNote, setCurrentNote] = useState({
...
editTitle: props.title,
editContent: props.content,
});
But the names of the input are in lowercase.
<input
name='edittitle'
...
/>
<textarea
name='editcontent'
...
/>
Thus in handleInputEdit you don't update the state but add new properties: edittitle and editcontent. Change the names to the camel case.
In React you cant assign to the component prop values, they are read-only.
const updateNote = () => {
...
props.title = currentNote.editTitle;
props.content = currentNote.editContent;
You need to use the handleUpdateNote function passed by the parent component instead. You have it commented for some reason.
<Note
...
//handleUpdateNote={handleUpdateNote}
/>
Check the code below. I think it does what you need.
function Note({ id, title, content, handleUpdateNote, deleteNote }) {
const [editNote, setEditNote] = React.useState(false);
const [currentNote, setCurrentNote] = React.useState({
id,
editTitle: title,
editContent: content,
});
const handleDelete = () => {
deleteNote(id);
};
const handleEdit = () => {
setEditNote(true);
setCurrentNote((prevValue) => ({ ...prevValue }));
};
const handleInputEdit = (event) => {
const { name, value } = event.target;
setCurrentNote((prevValue) => ({
...prevValue,
[name]: value,
}));
};
const updateNote = () => {
handleUpdateNote({
id: currentNote.id,
title: currentNote.editTitle,
content: currentNote.editContent
});
setEditNote(false);
};
return (
<div>
{editNote ? (
<div className='note'>
<input
type='text'
name='editTitle'
defaultValue={currentNote.editTitle}
onChange={handleInputEdit}
className='edit-input'
/>
<textarea
name='editContent'
defaultValue={currentNote.editContent}
row='1'
onChange={handleInputEdit}
className='edit-input'
/>
<button onClick={() => setEditNote(false)}>Cancel</button>
<button onClick={updateNote}>Save</button>
</div>
) : (
<div className='note' onDoubleClick={handleEdit}>
<h1>{title}</h1>
<p>{content}</p>
<button onClick={handleDelete}>DELETE</button>
</div>
)}
</div>
);
}
function CreateArea() {
return null;
}
function Container() {
const [notes, setNotes] = React.useState([
{ title: 'Words', content: 'hello, bye' },
{ title: 'Food', content: 'milk, cheese' }
]);
const addNote = (newNote) => {
setNotes((prevNotes) => {
return [...prevNotes, newNote];
});
};
const deleteNote = (id) => {
setNotes((prevNotes) => {
return prevNotes.filter((note, index) => {
return index !== id;
});
});
};
const handleUpdateNote = ({ id, title, content }) => {
const _notes = [];
for (let i = 0; i < notes.length; i++) {
if (i === id) {
_notes.push({ id, title, content });
} else {
_notes.push(notes[i]);
}
}
setNotes(_notes);
};
return (
<div>
<CreateArea addNote={addNote} />
{notes.map((note, index) => {
return (
<Note
key={index}
id={index}
title={note.title}
content={note.content}
deleteNote={deleteNote}
handleUpdateNote={handleUpdateNote}
/>
);
})}
</div>
);
}
function App() {
return (
<div>
<Container />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://unpkg.com/react#17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
Also, you can store the notes in an object or hash map instead of an array. For example
const [notes, setNotes] = React.useState({
'unique_id': { title: 'Words', content: 'hello, bye' }
});
Then in handleUpdateNote you have
setNotes((prev) => ({ ...prev, unique_id: { title, content } }))

Nested array in Context React won't update its state

I'm building a e-commerce store where I have the following data structure:
productsData.js
export const storeProducts = [
{
id: 1,
title: "Santos",
img: "img/pfs - black.png",
price: 59.70,
description: "Lorem Ipsum",
gender: ["Feminine", "Masculine"],
info:
"Lorem Ipsum",
inCart: false,
count: 0,
total: 0
}
];
export const detailProducts = {
id: 1,
title: "Pecadores Feitos Santos",
img: "img/pfs - black.png",
price: 59.70,
description: "Lorem ipsum",
gender: ["Feminine", "Masculine"],
info:
"Lorem ipsum.",
inCart: false,
count: 0,
total: 0
};
I have a Context React file that is my provider and consumer:
context.js
import React, { Component } from 'react'
import { storeProducts, detailProducts } from './productsData';
const ProductContext = React.createContext();
// Provider and Consumer
class ProductProvider extends Component {
state = {
products: [],
detailProducts: detailProducts,
cart: [],
modalOpen: false,
modalProduct: detailProducts,
cartTotal: 0
};
componentDidMount() {
this.setProducts();
}
setProducts = () => {
let tempProducts = [];
storeProducts.forEach(item => {
const singleItem = {...item};
tempProducts = [...tempProducts, singleItem];
});
this.setState(() => {
return { products: tempProducts };
// console.log("State products: ", storeProducts[0].color[0])
});
};
getItem = id => {
const product = this.state.products.find(item => item.id === id);
return product;
};
handleDetail = id => {
const product = this.getItem(id);
this.setState(() => {
return { detailProducts: product };
});
};
addToCart = id => {
let tempProducts = [...this.state.products];
const index = tempProducts.indexOf(this.getItem(id));
const product = tempProducts[index];
// console.log(product.gender);
product.inCart = true;
product.count = 1;
const price = product.price;
product.total = price;
this.setState(() => {
return { products: tempProducts, cart: [...this.state.cart,product] }
}, () => { this.addTotal();});
}
openModal = id => {
const product = this.getItem(id);
this.setState(() => {
return {modalProduct: product, modalOpen: true}
})
}
closeModal = () => {
this.setState(() => {
return {modalOpen: false}
})
}
increment = (id) => {
let tempCart = [...this.state.cart];
const selectedProduct = tempCart.find(item => item.id === id);
const index = tempCart.indexOf(selectedProduct);
const product = tempCart[index];
product.count = product.count + 1;
product.total = product.count * product.price;
this.setState(() => {
return {
cart: [...tempCart]
}
}, () => { this.addTotal() })
}
decrement = (id) => {
let tempCart = [...this.state.cart];
const selectedProduct = tempCart.find(item => item.id === id);
const index = tempCart.indexOf(selectedProduct);
const product = tempCart[index];
product.count = product.count - 1;
if(product.count === 0) {
this.removeItem(id);
}
else {
product.total = product.count * product.price;
this.setState(() => {
return {
cart: [...tempCart]
}
}, () => { this.addTotal() })
}
}
removeItem = (id) => {
let tempProducts = [...this.state.products];
let tempCart = [...this.state.cart];
tempCart = tempCart.filter(item => item.id !== id);
const index = tempProducts.indexOf(this.getItem(id));
let removedProduct = tempProducts[index];
removedProduct.inCart = false;
removedProduct.count = 0;
removedProduct.total = 0;
this.setState(() => {
return {
cart:[...tempCart],
products: [...tempProducts]
}
}, ()=> {
this.addTotal();
})
}
clearCart = () => {
this.setState(() => {
return { cart: [] };
}, () => {
this.setProducts();
this.addTotal();
})
}
addTotal = () => {
let total = 0;
this.state.cart.map(item => (total += item.total));
this.setState(() => {
return {
cartTotal: total
}
})
}
render() {
return (
<ProductContext.Provider value={{
...this.state,
handleDetail: this.handleDetail,
addToCart: this.addToCart,
openModal: this.openModal,
closeModal: this.closeModal,
increment: this.increment,
decrement: this.decrement,
removeItem: this.removeItem,
clearCart: this.clearCart
}}
>
{this.props.children}
</ProductContext.Provider>
)
}
}
const ProductConsumer = ProductContext.Consumer;
export { ProductProvider, ProductConsumer };
Everything works just fine, but here's where the problems start:
Details.js
import React, { Component } from 'react';
import { ProductConsumer } from '../context';
import { Link } from 'react-router-dom';
import { ButtonContainerSecondary } from './ButtonSecondary';
import { ButtonDetails } from './ButtonDetails';
import { ColorButton } from './ColorButton';
import PropTypes from 'prop-types';
export default class Details extends Component {
render() {
return (
<ProductConsumer>
{value => {
const {id, img, price, description, color, gender, info, title, inCart} = value.detailProducts;
return (
<div className="container pb-5">
<div className="row">
<div className="col-10 mx-auto text-center text-slanted my-5">
{gender.map((item, key) => (
<span>{" "}<ButtonDetails key={key} onClick={() => { this.setState({gender: key}); console.log(key)}}
</div>
</div>
</div>
)
}}
</ProductConsumer>
)
}
}
Details.propTypes = {
product: PropTypes.shape({
color: PropTypes.arrayOf(PropTypes.string),
gender: PropTypes.arrayOf(PropTypes.string)
})
}
I can't seem to figure out how to pass in the state in the nested array gender to the next level. I do get the console.log(key) right, but it gets lost as I move up to the cart. I would like to give the user the chance to choose from a feminine or masculine shirt:
CartItem.js
import React from 'react'
export default function CartItem({ item, value }) {
const {id, title, img, price, gender, total, count} = item;
const {increment, decrement, removeItem} = value;
return (
<div className="col-10 mx-auto col-lg-2">
<span className="d-lg-none">Product: </span> {title} {gender} {console.log(gender)}
</div>
);
}
Here the console.log(gender) returns both items of the array altogether ("FeminineMasculine").
I'm a newbie and would really appreciate your help. Sorry if anything!

Categories