What should I use instead of useSelector
or mapStateToProps
? Those run multiple times and change all values to the last one.
I have an e-commerce app, ProductDetails
component contains product reviews and I map those to the ProductReview
component to get user info that gets from user Id.
ProductDetails.js
import React, { useEffect } from "react";
import ProductReview from "../components/ProductReview";
import { useSelector, useDispatch } from 'react-redux';
import { getProductDetailsById } from "../Store/actions/productActions";
export default function ProductDetails(props) {
const dispatch = useDispatch()
const product = useSelector((state) => state.product)
useEffect(() => {
const { id } = props.match.params;
const payload = {
params: {
id,
},
};
dispatch(getProductDetailsById(payload));
},[dispatch, props.match.params]);
return (
<div>
{product.productDetails.reviews &&
product.productDetails.reviews.map((item , index) =>
(
<li key={item.userId}>
<ProductReview key={item.userId} userId={item.userId}
review={item.review}/>
</li> )
)}
)}
</div>
);
}
ProductReview.js
import React,{ useState, useEffect } from 'react';
import { getUSerById } from '../Store/actions/userAction';
import {useDispatch , useSelector} from 'react-redux';
export default function ProductReview(props) {
const dispatch = useDispatch()
const user = useSelector(state => state.user)
const {userId} = props;
useEffect(() => {
const payload = {
params : {
userId
}
}
dispatch(getUSerById(payload))
},[userId]);
return (
<div>
{user && user.user.firstName} : {props.review}
</div>
)
}
this part of the code runs multiple times and changes all user info values (user first name) to the last one. **All product reviews firstName
s change to the last one ** all same name
const user = useSelector(state => state.user)
Is there any way to get rid of this?? It runs currently when using Axios in the ProductReview
component with useState()
, but I want to use redux.
userReducer.js
import { userConstants } from "../actions/Types";
const initState = {
user: {},
loading: false,
error: null
};
export default (state = initState, action) => {
console.log(action.payload)
switch(action.type){
case userConstants.GET_USER_BY_ID_SUCCESS:
return state = {
...state,
user : action.payload.user,
loading: false,
error: null
}
case userConstants.GET_USER_BY_ID_FAILURE:
return state = {
state,
error: action.payload.error
}
default:
return state
}
}
From what I understand in the comments you need to store all users in your redux store in some way. For example you could do something like the following:
Change initState
with:
const initState = { users: {}, loading: false, error: null };
Change GET_USER_BY_ID_SUCCESS
reducer with (please pay attention that I'm using user.id
, but maybe your id is stored in some other property):
case userConstants.GET_USER_BY_ID_SUCCESS: return state = { ...state, users: { ...state.users, [action.payload.user.id]: action.payload.user }, loading: false, error: null }
Change useSelector with:
const users = useSelector(state => state.users)
Add:
const user = users[props.userId]
In this way you should have the correct user. If I miss something please tell me.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.