The reducer function works fine except that previously added object element to the item
array property gets over written whenever new object element is added.
For example, if state.item
contains {number: 1}
and I add {number: 2}
, it becomes [{number: 2},{number: 2}]
instead of [{number: 1},{number: 2}]
.
The reducer function:
const reducer = (state, action) => {
if (action.type === "ADD") {
let newItem = state.item.concat(action.addItem);
console.log("action.addItem:", action.addItem);
console.log("state.item:", state.item);
return { item: newItem };
}
};
Is there any solution this problem?
Thank You.
Parent Component:
import React from "react";
import { useReducer } from "react";
import { CreateContext } from "./CreateContext";
const initialState = {
item: [],
};
const reducer = (state, action) => {
if (action.type === "ADD") {
let newItem = state.item.concat(action.addItem);
console.log("action.addItem:", action.addItem);
console.log("state.item:", state.item);
return { item: newItem };
}
};
const AuthProvider = (props) => {
// define useReducer
const [state, dispatch] = useReducer(reducer, initialState);
// define handlers
const addItemHandler = (addItem) => {
console.log("addItemHandler");
dispatch({ type: "ADD", addItem: addItem });
};
const data = {
addItem: addItemHandler,
number: 0,
item: state.item,
};
return (
<CreateContext.Provider value={data}>
{props.children}
</CreateContext.Provider>
);
};
export default AuthProvider;
Child component:
import React, { useState, useContext } from "react";
import {
Button,
Card,
CardActionArea,
CardActions,
CardContent,
CardMedia,
makeStyles,
Typography,
Collapse,
TextField,
IconButton,
} from "@material-ui/core";
import clsx from "clsx";
import AddBoxIcon from "@material-ui/icons/AddBox";
import { Grid } from "@material-ui/core";
import { CreateContext } from "../Store/CreateContext";
const useStyles = makeStyles((theme) => ({
card: {
marginBottom: theme.spacing(5),
},
media: {
height: 250,
// smaller image for mobile
[theme.breakpoints.down("sm")]: {
height: 150,
},
},
priceDetail: {
marginLeft: theme.spacing(15),
},
numberTextField: {
width: 52,
},
addBtn: {
fontSize: 60,
},
}));
const data = {
id: null,
name: null,
price: null,
quantity: null,
};
// img and title from the feed component
const Food = ({ img, title, description, price, id }) => {
const classes = useStyles();
// expand the description
const [expanded, setExpanded] = React.useState(false);
const handleExpandClick = () => {
setExpanded(!expanded);
};
const newPrice = `RM${price.toFixed(2)} `;
////// process the form //////
//get quantity from TextField
const [quantity, setQuantity] = useState("");
const quantityHandler = (enteredQuantity) => {
console.log("enteredQuantity:", enteredQuantity);
setQuantity(enteredQuantity.target.value);
};
// use useContext
const AuthData = useContext(CreateContext);
const submitHandler = (e) => {
console.log("submit is pressed");
e.preventDefault();
data.id = id;
data.title = title;
console.log("data.id:", data.id);
data.price = price;
console.log("data.price:", data.price);
data.quantity = quantity;
console.log("quantity:", quantity);
AuthData.addItem(data);
console.log("AuthData:", AuthData.number);
};
return (
<Grid item xs={12} md={6}>
<form onSubmit={submitHandler}>
<Card className={classes.card} id={id}>
<CardActionArea>
<CardMedia className={classes.media} image={img} title="My Card" />
<CardContent>
<Typography gutterBottom variant="h5">
{title}
</Typography>
<Button
size="small"
color="primary"
className={clsx(classes.expand, {
[classes.expandOpen]: expanded,
})}
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="show more"
>
Learn More
</Button>
<CardActionArea>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
<Typography paragraph>{description}</Typography>
</CardContent>
</Collapse>
</CardActionArea>
</CardContent>
</CardActionArea>
<CardActions>
{" "}
<Typography variant="h6" className={classes.priceDetail}>
{newPrice}
</Typography>
<Typography variant="h6" className={""}>
x
</Typography>
<TextField
id={id}
label="amount"
type="number"
// value={}
// onChange={}
className={classes.numberTextField}
label=""
variant="outlined"
min="1"
max="5"
step="1"
defaultValue="0"
size="small"
onChange={quantityHandler}
input={id}
// ref={quantity}
/>
<IconButton aria-label="" onClick={""} type="submit">
<AddBoxIcon
color="secondary"
className={classes.addBtn}
></AddBoxIcon>
</IconButton>
</CardActions>
</Card>
</form>
</Grid>
);
};
export default Food;