How can I update a specific nested item in my reducer? - javascript

I have a reducer with the following structure:
{
"id": 8,
"location_name": "Some place",
"lat": "nn.nnnnnn",
"lng": "-nn.nnnnn",
"review_count": 3,
"score_avg": 3.00,
"reviews": [
{
"id": 14,
"userId": 1,
"userName": "JohnDoe",
"body": "Lorem Ipsum.",
"score": null,
"likes": 2,
"liked": true,
"review_pic": null
},
{
"id": 15,
"userId": 1,
"userName": "JohnDoe",
"body": "Lorem Ipsum.",
"score": null,
"likes": 0,
"liked": false,
"review_pic": null
},
{
"id": 13,
"userId": 4,
"userName": "JohnDoe",
"body": "Lorem Ipsum.",
"score": null,
"likes": 0,
"liked": false,
"review_pic": null
}
]
}
On the other hand, I have an action creator that returns an ID. I am trying to grab this ID to change liked to true and set likes+1 but the nested nature of this reducer's state is tripping me off.
EDIT: here's what I've been trying with my reducer with no luck:
import {GET_REVIEWS, CLEAR_REVIEWS, LIKE} from './reviewTypes';
const initialState = [];
const reviewReducer = (state = initialState, action) => {
switch(action.type) {
case GET_REVIEWS:
return action.payload;
case LIKE:
const reviews = state.reviews.map(review => {
if(review.id === action.payload) {
return {
...review,
liked: true,
likes: review.likes++
}
} else {
return review;
}
});
return {
...state,
reviews
}
case CLEAR_REVIEWS:
return [];
default:
return state;
}
}
export default reviewReducer;

I iterate over array.reviews with Array#some for finding the review with the desired id. If I found it than I increment the likes and set liked on true,
function updateLike(id, array) {
array.reviews.some(review => {
if (review.id==id) {
review.likes++;
review.liked = true;
return true;
}
});
}
let array = {
"id": 8,
"location_name": "Some place",
"lat": "nn.nnnnnn",
"lng": "-nn.nnnnn",
"review_count": 3,
"score_avg": 3.00,
"reviews": [
{
"id": 14,
"userId": 1,
"userName": "JohnDoe",
"body": "Lorem Ipsum.",
"score": null,
"likes": 2,
"liked": true,
"review_pic": null
},
{
"id": 15,
"userId": 1,
"userName": "JohnDoe",
"body": "Lorem Ipsum.",
"score": null,
"likes": 0,
"liked": false,
"review_pic": null
},
{
"id": 13,
"userId": 4,
"userName": "JohnDoe",
"body": "Lorem Ipsum.",
"score": null,
"likes": 0,
"liked": false,
"review_pic": null
}
]
};
updateLike(15, array);
console.log(array);

You can use Array#find to obtain the element with a specific id.
const data = { "id": 8, "location_name": "Some place", "lat": "nn.nnnnnn", "lng": "-nn.nnnnn", "review_count": 3, "score_avg": 3.00, "reviews": [ { "id": 14, "userId": 1, "userName": "JohnDoe", "body": "Lorem Ipsum.", "score": null, "likes": 2, "liked": true, "review_pic": null }, { "id": 15, "userId": 1, "userName": "JohnDoe", "body": "Lorem Ipsum.", "score": null, "likes": 0, "liked": false, "review_pic": null }, { "id": 13, "userId": 4, "userName": "JohnDoe", "body": "Lorem Ipsum.", "score": null, "likes": 0, "liked": false, "review_pic": null } ] };
let id = 13;
let obj = data.reviews.find(x => x.id === id);
if(obj) obj.liked = true;
console.log(data);

You don't have to use a reducer on that one, because u have only one array and you should be fine with useState, this code should work for you.
const onItemLike = (itemID) => {
setState(state.map(x => {
if(reviews.id === itemID)
return {...x, liked: true, likes: state.reviews[x].likes+1}
}))
}

Related

How can i calculate the rating in the rating array and still return it as a response

This is the sample JSON response from the Backend, the rating is in ratings array and the value is rating, so I want to calculate the average rating for each course and still return it as a response to frontend,
I tried using Object.Assign() but is worked well when i am fetching just one course but when i am fetching all courses, it doesn't work.
please i need help
{
"message": "Fetched successfully",
"status": "Success",
"statusCode": 200,
"data": {
"items": [
{
"id": 210,
"courseUuid": "93b760a7-505e-41bf-b57e-d84ecf53255f",
"userId": 2,
"title": "Complete Angularzero to hero",
"imageUrl": "https://our-akademy-uploads.s3.eu-west-1.amazonaws.com/courses/1655654436946-f02118c8-e3e9-44e5-8913-48d4f45cd816.png",
"slugUrl": "Complete-Angularzero-to-hero-19-06-2022-93b760a7-505e-41bf-b57e-d84ecf53255f",
"amount": "50,600",
"averageRating": "11.5",
"createdAt": "2022-06-19T16:00:43.009Z",
"updatedAt": "2022-06-19T23:27:46.073Z",
"user": {
"id": 2,
"userUuid": "b1f8def8-aa1d-4a57-b743-174a6ee738ec",
"email": "jessika76#hotmail.com",
"nawisNumber": "NAWIS/2022/54682884"
},
"category": {
"id": 1,
"categoryUuid": "3a4def94-dd1a-451c-8f84-476096203710",
"name": "Front-End Development",
"slugUrl": "Front-End-Development-18-06-2022-ec0a7634-b710-4723-b646-4cde33d3d15a"
},
"duration": {
"id": 23,
"durationUuid": "3500b0d0-8d98-46d6-80d8-6363c09e887c",
"duration": "5 Months"
},
"enrollments": [
{
"id": 1,
"paymentStatus": "Not Completed",
"createdAt": "2022-06-19T16:04:22.375Z",
"user": {
"id": 3,
"userUuid": "ad0b0ad4-368d-4f09-ae99-80d2bcaed3d6",
"email": "damion.jacobs84#yahoo.com",
"nawisNumber": "NAWIS/2022/12758991"
}
},
{
"id": 2,
"paymentStatus": "Not Completed",
"createdAt": "2022-06-19T16:07:37.059Z",
"user": {
"id": 6,
"userUuid": "cbfbc6a7-dfd7-4f74-a545-a1423ccdb0f3",
"email": "olaf_bailey#hotmail.com",
"nawisNumber": "NAWIS/2022/11177867"
}
}
],
"ratings": [
{
"id": 1,
"rating": 2,
"review": "some text here",
"createdAt": "2022-06-19T16:04:40.339Z",
"user": {
"id": 3,
"userUuid": "ad0b0ad4-368d-4f09-ae99-80d2bcaed3d6",
"email": "damion.jacobs84#yahoo.com"
}
},
{
"id": 2,
"rating": 5,
"review": "some text here",
"createdAt": "2022-06-19T16:07:23.798Z",
"user": {
"id": 6,
"userUuid": "cbfbc6a7-dfd7-4f74-a545-a1423ccdb0f3",
"email": "olaf_bailey#hotmail.com"
}
}
]
},
{
"id": 208,
"courseUuid": "16855bd6-dd18-420a-8611-bc77bbda818c",
"userId": 2,
"title": "Complete Vuejs zero to hero",
"imageUrl": "https://our-akademy-uploads.s3.eu-west-1.amazonaws.com/courses/1655653347091-cfee6022-0d3a-43e2-b780-986eda2607ed.png",
"slugUrl": "undefined-19-06-2022-16855bd6-dd18-420a-8611-bc77bbda818c",
"amount": "0",
"averageRating": "0",
"createdAt": "2022-06-19T15:42:30.273Z",
"updatedAt": "2022-06-19T15:53:07.726Z",
"user": {
"id": 2,
"userUuid": "b1f8def8-aa1d-4a57-b743-174a6ee738ec",
"email": "jessika76#hotmail.com",
"nawisNumber": "NAWIS/2022/54682884"
},
"category": {
"id": 1,
"categoryUuid": "3a4def94-dd1a-451c-8f84-476096203710",
"name": "Front-End Development",
"slugUrl": "Front-End-Development-18-06-2022-ec0a7634-b710-4723-b646-4cde33d3d15a"
},
"duration": {
"id": 23,
"durationUuid": "3500b0d0-8d98-46d6-80d8-6363c09e887c",
"duration": "5 Months"
},
"enrollments": [],
"ratings": []
},
{
"id": 207,
"courseUuid": "bdb3ee71-0c0b-41d8-9049-5fa6a2a230f3",
"userId": 2,
"title": "Complete Vuejs zero to hero",
"imageUrl": "https://our-akademy-uploads.s3.eu-west-1.amazonaws.com/courses/1655653325613-dda17c5c-2a4a-435a-99cb-ad28ea01bbb0.png",
"slugUrl": "Complete-Vuejs-zero-to-hero-19-06-2022-bdb3ee71-0c0b-41d8-9049-5fa6a2a230f3",
"amount": "50,600",
"averageRating": "0",
"createdAt": "2022-06-19T15:42:12.687Z",
"updatedAt": "2022-06-19T15:42:12.687Z",
"user": {
"id": 2,
"userUuid": "b1f8def8-aa1d-4a57-b743-174a6ee738ec",
"email": "jessika76#hotmail.com",
"nawisNumber": "NAWIS/2022/54682884"
},
"category": {
"id": 1,
"categoryUuid": "3a4def94-dd1a-451c-8f84-476096203710",
"name": "Front-End Development",
"slugUrl": "Front-End-Development-18-06-2022-ec0a7634-b710-4723-b646-4cde33d3d15a"
},
"duration": {
"id": 23,
"durationUuid": "3500b0d0-8d98-46d6-80d8-6363c09e887c",
"duration": "5 Months"
},
"enrollments": [],
"ratings": []
}
],
"meta": {
"totalItems": 209,
"itemCount": 3,
"itemsPerPage": 6,
"totalPages": 35,
"currentPage": 1
},
"links": {
"first": "http://ourakademy.com/api/v1/courses?limit=6",
"previous": "",
"next": "http://ourakademy.com/api/v1/courses?page=2&limit=6",
"last": "http://ourakademy.com/api/v1/courses?page=35&limit=6"
}
}
}
Assuming you put your json response in sampleJson variable
let sampleJson = YOUR JSON RESPONE
let sum = 0
let noOfRatings = 0
if(sampleJson && sampleJson.data && sampleJson.data.items){
sampleJson.data.items.forEach(item => {
item.ratings.forEach(i => {
if (i && i.rating) { sum += i.rating; noOfRatings++ }
})
});
if(sum && noOfRatings){
let averateRating = sum / noOfRatings
console.log('Average Rating : ',averateRating)
}
}
You will get average rating using this code.
Hope it helps :)
This is how i fixed the problem
const courses: any = await this.find();
for (let i = 0; i < courses.length; i++) {
const course = courses[i];
const sum: any = course.ratings.reduce((accumulator, object) => {
return accumulator + object.rating;
}, 0);
courses[i] = {
...course,
avg: sum / course.ratings.length,
};
}
return courses;

How to add value to object and remove current value?

I have data like this :
users = [{
"emp_id": 1,
"user": {
"emp_full_name": "Test",
"emp_email": "test#gmail.com",
"emp_phone_no": null,
"preferred_work_type": null
},
"hashtag": {
"id": 1,
"name": "NodeJs",
"hashtag_group_id": 1
},
"difficulty": "HARD"
}, {
"emp_id": 2,
"user": {
"emp_full_name": "test2",
"emp_email": "test2#gmail.com",
"emp_phone_no": null,
"preferred_work_type": null
},
"hashtag": {
"id": 1,
"name": "NodeJs",
"hashtag_group_id": 1
},
"difficulty": "EASY"
}, {
"emp_id": 1,
"user": {
"emp_full_name": "Test",
"emp_email": "test#gmail.com",
"emp_phone_no": null,
"preferred_work_type": null
},
"hashtag": {
"id": 4,
"name": "Javascript",
"hashtag_group_id": 1
},
"difficulty": "HARD"
}]
I want to add hashtag to same the object that has the same emp_id. If emp_id has more than one data then the data that has the emp_id with the single hashtag data should be removed.
So basically this is what I expected:
[{
"emp_id": 1,
"user": {
"emp_full_name": "Test",
"emp_email": "test#gmail.com",
"emp_phone_no": null,
"preferred_work_type": null
},
"hashtag": [{
"id": 1,
"name": "NodeJs",
"hashtag_group_id": 1
}, {
"id": 4,
"name": "Javascript",
"hashtag_group_id": 1
}],
"difficulty": "HARD"
}, {
"emp_id": 2,
"user": {
"emp_full_name": "test2",
"emp_email": "test2#gmail.com",
"emp_phone_no": null,
"preferred_work_type": null
},
"hashtag": {
"id": 1,
"name": "NodeJs",
"hashtag_group_id": 1
},
"difficulty": "EASY"
}]
How to transform the data like that?
I have no idea how to solve that, I tried using filter(), and map() with some validation condition, but couldn't get it to work.
You can use .reduce() with .findIndex(). Try this
let users = '[{"emp_id": 1, "user": {"emp_full_name": "Test", "emp_email": "test#gmail.com", "emp_phone_no": null, "preferred_work_type": null }, "hashtag": {"id": 1, "name": "NodeJs", "hashtag_group_id": 1 }, "difficulty": "HARD"}, {"emp_id": 2, "user": {"emp_full_name": "test2", "emp_email": "test2#gmail.com", "emp_phone_no": null, "preferred_work_type": null }, "hashtag": {"id": 1, "name": "NodeJs", "hashtag_group_id": 1 }, "difficulty": "EASY"}, {"emp_id": 1, "user": {"emp_full_name": "Test", "emp_email": "test#gmail.com", "emp_phone_no": null, "preferred_work_type": null }, "hashtag": {"id": 4, "name": "Javascript", "hashtag_group_id": 1 }, "difficulty": "HARD"} ]';
users = JSON.parse(users)
users = users.reduce((arr, o) => {
let idx = arr.findIndex(({emp_id}) => emp_id === o.emp_id);
if( idx !== -1 ) arr[idx].hashtag = [].concat(arr[idx].hashtag, o.hashtag)
else arr.push(o)
return arr;
}, []);
console.log(users)
You could create a Map keyed by emp_id and collect the users by that key. When there is already an entry, extend the hashtag using [].concat. This will create an array if it wasn't an array yet.
const users = [{"emp_id": 1,"user": {"emp_full_name": "Test","emp_email": "test#gmail.com","emp_phone_no": null,"preferred_work_type": null},"hashtag": {"id": 1,"name": "NodeJs","hashtag_group_id": 1},"difficulty": "HARD"},{"emp_id": 2,"user": {"emp_full_name": "test2","emp_email": "test2#gmail.com","emp_phone_no": null,"preferred_work_type": null},"hashtag": {"id": 1,"name": "NodeJs","hashtag_group_id": 1},"difficulty": "EASY"},{"emp_id": 1,"user": {"emp_full_name": "Test","emp_email": "test#gmail.com","emp_phone_no": null,"preferred_work_type": null},"hashtag": {"id": 4,"name": "Javascript","hashtag_group_id": 1},"difficulty": "HARD"}];
const map = new Map;
for (const user of users) {
const match = map.get(user.emp_id);
if (match) match.hashtag = [].concat(match.hashtag, user.hashtag);
else map.set(user.emp_id, {...user});
}
const result = [...map.values()];
console.log(result);

How to dynamically map over object

I need to dynamically insert a list of values as the key to be mapped over. The list here is employeeTypes. I need to map() over every role.supervisors and every role.employees..
Attempt:
export default function EmployeesByDepartmentList({ department }) {
const employeeTypes = ["supervisors", "employees"];
return (
<div className={styles.departmentSection} key={department.id}>
{department.roles.length
? department.roles.map((role) =>
employeeTypes.forEach((type) => { // this is my attempt at iterating over each item in employeeTypes to use as the role key
role[type].map((item) => (
<ListLinkItem
key={item.id}
id={item.id}
href={`employees/${item.id}/`}
>
<EmployeeImage
src={item.image}
alt={item.first_name + item.last_name}
/>
</ListLinkItem>
));
})
)
: null}
</div>
);
}
I am sure it is easy, I just can't seem to visualize what I need atm. All help appreciated!
Edit:
This is the department object:
{
"id": 2,
"roles": [
{
"id": 1,
"employees": [],
"supervisors": [
{
"id": 8,
"role": "Casino Supervisor",
"last_login": "2022-05-06T13:34:44.934187-07:00",
"is_superuser": false,
"username": "T2Admin1",
"is_staff": true,
"is_active": true,
"date_joined": "2022-04-06T19:42:22-07:00",
"first_name": "T2Admin",
"last_name": "Admin1",
"badge_num": "1234",
"email_notifications": true,
"sms_notifications": true,
"points": 0,
"image": "/media/images/profile_pics/dealer.jpg",
"supervisor": null,
"company": 2,
"groups": [
1,
3
],
"user_permissions": []
},
],
"name": "Casino Supervisor",
"supervisor": null,
"group": 1,
"company": 2
},
{
"id": 11,
"employees": [
{
"id": 4,
"role": "Dealer",
"last_login": null,
"is_superuser": false,
"username": "T2Dealer2",
"is_staff": false,
"is_active": true,
"date_joined": "2022-04-06T19:32:08-07:00",
"first_name": "T2Dealer",
"last_name": "Dealer2",
"badge_num": "1234",
"email_notifications": true,
"sms_notifications": true,
"points": 0,
"image": "/media/images/profile_pics/dealer.jpg",
"supervisor": null,
"company": 2,
"groups": [
2
],
"user_permissions": []
},
],
"supervisors": [],
"name": "Dealer",
"supervisor": null,
"group": 2,
"company": 2
}
],
"created_on": "2022-04-14T16:15:27.299700-07:00",
"updated_on": "2022-04-21T12:31:24.773872-07:00",
"name": "Casino"
}
You could try something like this:
const department = {
"id": 2,
"roles": [{
"id": 1,
"employees": [],
"supervisors": [{
"id": 8,
"role": "Casino Supervisor",
"last_login": "2022-05-06T13:34:44.934187-07:00",
"is_superuser": false,
"username": "T2Admin1",
"is_staff": true,
"is_active": true,
"date_joined": "2022-04-06T19:42:22-07:00",
"first_name": "T2Admin",
"last_name": "Admin1",
"badge_num": "1234",
"email_notifications": true,
"sms_notifications": true,
"points": 0,
"image": "/media/images/profile_pics/dealer.jpg",
"supervisor": null,
"company": 2,
"groups": [
1,
3
],
"user_permissions": []
}, ],
"name": "Casino Supervisor",
"supervisor": null,
"group": 1,
"company": 2
},
{
"id": 11,
"employees": [{
"id": 4,
"role": "Dealer",
"last_login": null,
"is_superuser": false,
"username": "T2Dealer2",
"is_staff": false,
"is_active": true,
"date_joined": "2022-04-06T19:32:08-07:00",
"first_name": "T2Dealer",
"last_name": "Dealer2",
"badge_num": "1234",
"email_notifications": true,
"sms_notifications": true,
"points": 0,
"image": "/media/images/profile_pics/dealer.jpg",
"supervisor": null,
"company": 2,
"groups": [
2
],
"user_permissions": []
}, ],
"supervisors": [],
"name": "Dealer",
"supervisor": null,
"group": 2,
"company": 2
}
],
"created_on": "2022-04-14T16:15:27.299700-07:00",
"updated_on": "2022-04-21T12:31:24.773872-07:00",
"name": "Casino"
}
department.roles.map(role => {
role.employees.map(employee => console.log("do something with this employee: ", employee))
role.supervisors.map(supervisor => console.log("do something with this supervisor: ", supervisor))
})
You can fix your component like this. Here is the working example https://codesandbox.io/embed/goofy-aryabhata-4bbonf?fontsize=14&hidenavigation=1&theme=dark
export default function App() {
return (
<div className="App">
{department.roles.map((role) =>
(role?.supervisors?.map((supervisor) => (
<div>{supervisor?.id}</div>
))).concat((role?.employees?.map((employee) => (
<div>{employee?.id}</div>
))))
)
}
</div>
);
}
With the help of GitHub CoPilot (writing psuedocode comments), I was able to solve the problem using employeeTypes.map() then making sure that the Array.Prototype() has a return statement in it - as such:
export default function EmployeesByDepartmentList({ department }) {
const employeeTypes = ["supervisors", "employees"];
return (
<div className={styles.departmentSection} key={department.id}>
{department.roles.length
? department.roles.map((role) =>
// iterate over each role, with each employeeType as the key
employeeTypes.map((employeeType) => {
// return the employees
return role[employeeType].map((item) => (
<ListLinkItem
key={item.id}
id={item.id}
href={`employees/${item.id}/`}
>
<EmployeeImage
src={item.image}
alt={item.first_name + item.last_name}
/>
</ListLinkItem>
));
})
)
: null}
</div>
);
}
This should be roughly what you're looking for. Your first goal is to get all relevant people into one flat array. After that, it's easy to iterate using Array#map. Something along the lines of this:
export default function EmployeesByDepartmentList({ department }) {
const employeeTypes = ['supervisors', 'employees'];
const allPeople = employeeTypes
.map(type => department.roles.find(role => type in role)?.[type])
.filter(Boolean)
.flat();
return (
<div className={styles.departmentSection} key={department.id}>
{allPeople.map(person => (
<ListLinkItem key={person.id} id={person.id} href={`employees/${person.id}/`}>
<EmployeeImage src={person.image} alt={person.first_name + person.last_name} />
<div className={styles.employeeCardInfoContainer}>
<div className={styles.listItemTitle}>
{person.first_name} {person.last_name}
</div>
<div className={styles.employeeCardRole}>{person.role}</div>
</div>
<div className={styles.employeeCardButtonContainer}>
<ArrowCircleIcon />
</div>
</ListLinkItem>
))}
</div>
);
}

Object with nested array to filter, want to return entire object with new filtered array

I'm attempting to remove an object out of an array nested within my movie object and then copy it to a new variable. So my original object looks like this:
{
"id": 1,
"title": "Avatar",
"movieLength": 162,
"releaseDate": "2009-12-18",
"trailerUrl": "https://www.youtube.com/watch?v=5PSNL1qE6VY",
"genre": {
"id": 1,
"genre": "Action"
},
"rating": {
"id": 3,
"rating": "PG-13"
},
"director": {
"id": 1,
"lastName": "Cameron",
"firstName": "James"
},
"actors": [
{
"id": 2,
"lastName": "Worthington",
"firstName": "Sam"
},
{
"id": 3,
"lastName": "Weaver",
"firstName": "Sigourney"
},
{
"id": 4,
"lastName": "Saldana",
"firstName": "Zoe"
}
],
"comments": []
}
and what I'm doing right now is
const updatedMovie = const updatedMovie = movie.actors.filter((actor) => actor.id !== id);
but as you know that only returns the array of actors I filtered. I want to copy the entire object with the newly filtered actors so the object will come out like this (removing actor id 3):
{
"id": 1,
"title": "Avatar",
"movieLength": 162,
"releaseDate": "2009-12-18",
"trailerUrl": "https://www.youtube.com/watch?v=5PSNL1qE6VY",
"genre": {
"id": 1,
"genre": "Action"
},
"rating": {
"id": 3,
"rating": "PG-13"
},
"director": {
"id": 1,
"lastName": "Cameron",
"firstName": "James"
},
"actors": [
{
"id": 2,
"lastName": "Worthington",
"firstName": "Sam"
},
{
"id": 4,
"lastName": "Saldana",
"firstName": "Zoe"
}
],
"comments": []
}
I've tried reading around but I'm not having any luck getting any solutions to work with me, so if anyone can help or point me in the right direction that would be great!
If you want to mutate the existing object, just assign the result of the .filter to the .actors property.
movie.actors = movie.actors.filter((actor) => actor.id !== id);
console.log(movie);
If you want to keep the existing object unmutated, spread the rest of the properties into a new object while filtering.
const updatedMovie = {
...movie,
actors: movie.actors.filter((actor) => actor.id !== id)
};
console.log(updatedMovie);
const movies = {
"id": 1,
"title": "Avatar",
"movieLength": 162,
"releaseDate": "2009-12-18",
"trailerUrl": "https://www.youtube.com/watch?v=5PSNL1qE6VY",
"genre": {
"id": 1,
"genre": "Action"
},
"rating": {
"id": 3,
"rating": "PG-13"
},
"director": {
"id": 1,
"lastName": "Cameron",
"firstName": "James"
},
"actors": [
{
"id": 2,
"lastName": "Worthington",
"firstName": "Sam"
},
{
"id": 3,
"lastName": "Weaver",
"firstName": "Sigourney"
},
{
"id": 4,
"lastName": "Saldana",
"firstName": "Zoe"
}
],
"comments": []
}
const id = 3; // or any other id you want
const actors = movies.actors.filter(actor => actor.id != id)
const newMovies = Object.assign({}, movies , { actors })
console.log(newMovies)

React native with redux shopping cart

Am trying to create a shopping cart in react native, my problem is whenever i add a product to the shopping cart it is added through the following action:
export const addToCart = (item) => {
return (dispatch) =>{
dispatch({
type:ADD_TO_CART,
payload: {item}});
}
}
this is the reducer:
import {REMOVE_FROM_CART,ADD_TO_CART,UPDATE_CART_QUANTITY,GET_CATEGORIES, GET_PRODUCTS,
MODAL_STATE,MODAL_STATE_HIDE,ADDRESS_CHANGED,SELECTED_ITEMS} from '../actions/types';
const INITIAL_STATE = {
products:'',
cart:[],
category:'',
isVisible:false,
address:'',
selectedItem:[]
}
export default function(state=INITIAL_STATE, action){
let cart = state.cart;
switch(action.type){
case ADD_TO_CART:
return{...state, cart:[...state.cart, action.payload]}
case REMOVE_FROM_CART:
return{cart:[...state.cart.filter(item => item.id != action.payload)]}
// {...state, cart:[...state.cart.filter((id)=>{ id !== action.payload})]}
case UPDATE_CART_QUANTITY:
return {
...state,
cart: state.cart.map(cart=> cart.id === action.payload.item.id ?
{ ...cart, quantity: action.payload.value} :
cart
)
};
case GET_CATEGORIES:
return{...state, category:action.payload}
case GET_PRODUCTS:
return{...state, products:action.payload}
case MODAL_STATE:
return{...state, isVisible:true}
case MODAL_STATE_HIDE:
return{...state, isVisible:false}
case ADDRESS_CHANGED:
return{...state, address:action.payload}
case SELECTED_ITEMS:
return{...state, selectedItem:[...state.selectedItem, action.payload]}
default:
return state
}
}
BUT when i try to access the cart through mapping state to props in the cart component, it returns undefined is not an object, when console log typeof(cart) from cart component it says its an object:
this is the mapstatetoprops function:
const mapStateToProps = (state) => {
return{
cartItems:state.product_reducer.cart,
modalValue:state.product_reducer.isVisible,
total: state.product_reducer.cart.reduce(
in the array
(accumulatedTotal, cartItem) =>
accumulatedTotal + cartItem.price * cartItem.quantity,
0
)
}
}
this is the json product data that i add to the cart there are two products with 7 and 8 as ids:
{
"product": [
{
"id": 8,
"name": "asad",
"quantity": 1,
"type": "already",
"description": null,
"price": "20000.00",
"ingredients": null,
"deliveryfee": "0.00",
"supplier": null,
"duration": "3",
"category_id": 3,
"created_at": "2020-05-03 15:03:23",
"updated_at": "2020-05-03 15:03:23",
"deleted_at": null,
"photo": {
"id": 19,
"model_type": "App\\Product",
"model_id": 8,
"collection_name": "photo",
"name": "5eaedd370c100_jamies-iced-green-tea",
"file_name": "5eaedd370c100_jamies-iced-green-tea.jpg",
"mime_type": "image/jpeg",
"disk": "public",
"size": 36610,
"manipulations": [],
"custom_properties": {
"generated_conversions": {
"thumb": true
}
},
"responsive_images": [],
"order_column": 19,
"created_at": "2020-05-03 15:03:24",
"updated_at": "2020-05-03 15:03:24",
"url": "http://192.168.0.112/kwenu/storage/app/public/19/5eaedd370c100_jamies-iced-green-tea.jpg",
"thumbnail": "http://192.168.0.112/kwenu/storage/app/public/19/conversions/5eaedd370c100_jamies-iced-green-tea-thumb.jpg"
},
"sliderimages": [],
"tags": [
{
"id": 1,
"name": "Avocado",
"supplier": null,
"created_at": "2020-04-23 09:35:00",
"updated_at": "2020-04-23 09:35:00",
"deleted_at": null,
"picture": [],
"pivot": {
"product_id": 8,
"product_tag_id": 1
},
"media": []
},
{
"id": 2,
"name": "cushew",
"supplier": "Fruit Salads",
"created_at": "2020-04-27 13:03:35",
"updated_at": "2020-04-27 13:03:35",
"deleted_at": null,
"picture": [],
"pivot": {
"product_id": 8,
"product_tag_id": 2
},
"media": []
}
],
"media": [
{
"id": 19,
"model_type": "App\\Product",
"model_id": 8,
"collection_name": "photo",
"name": "5eaedd370c100_jamies-iced-green-tea",
"file_name": "5eaedd370c100_jamies-iced-green-tea.jpg",
"mime_type": "image/jpeg",
"disk": "public",
"size": 36610,
"manipulations": [],
"custom_properties": {
"generated_conversions": {
"thumb": true
}
},
"responsive_images": [],
"order_column": 19,
"created_at": "2020-05-03 15:03:24",
"updated_at": "2020-05-03 15:03:24",
"url": "http://192.168.0.112/kwenu/storage/app/public/19/5eaedd370c100_jamies-iced-green-tea.jpg",
"thumbnail": "http://192.168.0.112/kwenu/storage/app/public/19/conversions/5eaedd370c100_jamies-iced-green-tea-thumb.jpg"
}
]
},
{
"id": 7,
"name": "Fruity",
"quantity": 1,
"type": "own",
"description": null,
"price": "18000.00",
"ingredients": null,
"deliveryfee": "0.00",
"supplier": null,
"duration": "1",
"category_id": 2,
"created_at": "2020-05-03 11:06:52",
"updated_at": "2020-05-03 11:06:52",
"deleted_at": null,
"photo": {
"id": 18,
"model_type": "App\\Product",
"model_id": 7,
"collection_name": "photo",
"name": "5eaea5c67a659_grilledchicken",
"file_name": "5eaea5c67a659_grilledchicken.jpg",
"mime_type": "image/jpeg",
"disk": "public",
"size": 13069,
"manipulations": [],
"custom_properties": {
"generated_conversions": {
"thumb": true
}
},
"responsive_images": [],
"order_column": 18,
"created_at": "2020-05-03 11:06:53",
"updated_at": "2020-05-03 11:06:56",
"url": "http://192.168.0.112/kwenu/storage/app/public/18/5eaea5c67a659_grilledchicken.jpg",
"thumbnail": "http://192.168.0.112/kwenu/storage/app/public/18/conversions/5eaea5c67a659_grilledchicken-thumb.jpg"
},
"sliderimages": [],
"tags": [
{
"id": 1,
"name": "Avocado",
"supplier": null,
"created_at": "2020-04-23 09:35:00",
"updated_at": "2020-04-23 09:35:00",
"deleted_at": null,
"picture": [],
"pivot": {
"product_id": 7,
"product_tag_id": 1
},
"media": []
},
{
"id": 2,
"name": "cushew",
"supplier": "Fruit Salads",
"created_at": "2020-04-27 13:03:35",
"updated_at": "2020-04-27 13:03:35",
"deleted_at": null,
"picture": [],
"pivot": {
"product_id": 7,
"product_tag_id": 2
},
"media": []
}
],
"media": [
{
"id": 18,
"model_type": "App\\Product",
"model_id": 7,
"collection_name": "photo",
"name": "5eaea5c67a659_grilledchicken",
"file_name": "5eaea5c67a659_grilledchicken.jpg",
"mime_type": "image/jpeg",
"disk": "public",
"size": 13069,
"manipulations": [],
"custom_properties": {
"generated_conversions": {
"thumb": true
}
},
"responsive_images": [],
"order_column": 18,
"created_at": "2020-05-03 11:06:53",
"updated_at": "2020-05-03 11:06:56",
"url": "http://192.168.0.112/kwenu/storage/app/public/18/5eaea5c67a659_grilledchicken.jpg",
"thumbnail": "http://192.168.0.112/kwenu/storage/app/public/18/conversions/5eaea5c67a659_grilledchicken-thumb.jpg"
}
]
}
]
}
THE PROBLEM IS INSTEAD OF STATE RETURNING cart AS AN ARRAY OF OBJECTS, IT RETURNS AN OBJECT OF OBJECTS, THANK YOU IN ADVANCE
i see addToCart action take the payload as an object { item }
and you try to access in reducer by action.payload without item
so
you can change
case ADD_TO_CART:
return{...state, cart:[...state.cart, action.payload.item]}
Or just update add to cart to be like so && all actions should be same
export const addToCart = (payload) => {
return (dispatch) =>{
dispatch({
type:ADD_TO_CART,
payload
}
}
Fixed it by changing the name of the cart array in the reducer from
const INITIAL_STATE = {
products:'',
cart:[],
category:'',
isVisible:false,
address:'',
selectedItem:[]
}
to:
const INITIAL_STATE = {
products:'',
carts:[],
category:'',
isVisible:false,
address:'',
selectedItem:[]
}
and the creating a class function for rendering the items in the cart component which i supplied to the renderitem function in the flatlist now the cart returns an array of objects. THANK YOU MUSTAFA FOR YOUR CONCERN

Categories

Resources