Trying to update deprecated/obsolete code for recent React/Redux versions - reactjs

I have been following a tutorial to make a MERN e-commerce website:
Youtube Video Tutorial: VIDEO
Github containing all the code from the creator of the video: Github
And since it was published at December 2020, I encounter some deprecated/obsolete code that used to work for the creator of the video but doesn't work anymore.
I managed to solve most of the issues but at 3:31:26 of the video, he gets a bug and fixes it easily. The problem is that his solution doesn't make sense and it doesn't work. I have a different error but the error is logically generated. If you look at the video you will notice he does "cartItems.map" but when console logging cartItems it gives me that it is an object. I've tried replacing my code with his, but nothing. Replacing with his Github's code. Neither.
The error I receive when I click on "add to cart" from the product's page
This is where the web browser points to in the code, which is where cartItems is used as an array but it isn't (I also tried [...Array(cartItems)].map and didn't work
CartScreen.jsx
import './CartScreen.css'
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from "react-router-dom";
// Components
import CartItem from "../components/CartItem";
const CartScreen = () => {
const dispatch = useDispatch();
const cart = useSelector(state => state.cart);
const { cartItems } = cart;
return (
<div className='cartscreen'>
<div className='cartscreen__left'>
<h2>Shopping Cart</h2>
{console.log(typeof cartItems)}
{cartItems.length === 0 ? (
<div>
Your Cart is empty <Link to="/">Go Back</Link>
</div>
) : (
cartItems.map((item) =>
<CartItem item={item} />
))}
</div>
<div className='cartscreen__right'>
<div className='cartscreen__info'>
<p>Subtotal (0) items</p>
<p>$499.99</p>
<div>
<button>Proceed to Checkout</button>
</div>
</div>
</div>
</div>
)
}
export default CartScreen;
CartItem.jsx
import "./CartItem.css";
import { Link } from "react-router-dom";
const CartItem = ({ item, qtyChangeHandler, removeHandler }) => {
return (
<div className="cartitem">
<div className="cartitem__image">
<img src={item.imageUrl} alt={item.name} />
</div>
<Link to={`/product/${item.product}`} className="cartItem__name">
<p>{item.name}</p>
</Link>
<p className="cartitem__price">${item.price}</p>
<select
value={item.qty}
onChange={(e) => qtyChangeHandler(item.product, e.target.value)}
className="cartItem__select"
>
{[...Array(item.countInStock).keys()].map((x) => (
<option key={x + 1} value={x + 1}>
{x + 1}
</option>
))}
</select>
<button
className="cartItem__deleteBtn"
onClick={() => removeHandler(item.product)}
>
<i className="fas fa-trash"></i>
</button>
</div>
);
};
export default CartItem;
cartActions.jsx
import * as actionTypes from '../constants/cartConstants';
import axios from 'axios';
export const addToCart = (id, qty) => async (dispatch, getState) => {
const { data } = await axios.get(`/api/products/${id}`);
dispatch({
type: actionTypes.ADD_TO_CART,
payload: {
product: data.id,
name: data.new,
imageURL: data.imageUrl,
price: data.price,
countInStock: data.countInStock,
qty
},
});
localStorage.setItem('cart', JSON.stringify(getState().cart.cartItems));
};
export const removeFromCart = (id) => (dispatch, getState) =>{
dispatch({
type: actionTypes.REMOVE_FROM_CART,
payload: id
});
localStorage.setItem('cart', JSON.stringify(getState().cart.cartItems));
};
ProductScreen.jsx
import "./ProductScreen.css";
import { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useParams, useNavigate } from "react-router-dom";
// Actions
import { getProductDetails } from "../redux/actions/productActions";
import { addToCart } from "../redux/actions/cartActions";
const ProductScreen = ({ history }) => {
const [qty, setQty] = useState(1);
const dispatch = useDispatch();
const productDetails = useSelector((state) => state.getProductDetails);
const { loading, error, product } = productDetails;
const { id } = useParams();
const navigate = useNavigate();
useEffect(() => {
if (product && id !== product._id) {
dispatch(getProductDetails(id));
}
}, [dispatch, product]);
const addToCartHandler = () => {
dispatch(addToCart(product._id, qty));
navigate("/cart");
};
return (
<div className="productscreen">
{loading ? (
<h2>Loading...</h2>
) : error ? (
<h2>{error}</h2>
) : (
<>
<div className="productscreen__left">
<div className="left__image">
<img src={product.imageUrl} alt={product.name} />
</div>
<div className="left__info">
<p className="left__name">{product.name}</p>
<p>Price: ${product.price}</p>
<p>Description: {product.description}</p>
</div>
</div>
<div className="productscreen__right">
<div className="right__info">
<p>
Price:
<span>${product.price}</span>
</p>
<p>
Status:
<span>
{product.countInStock > 0 ? "In Stock" : "Out of Stock"}
</span>
</p>
<p>
Qty
<select value={qty} onChange={(e) => setQty(e.target.value)}>
{[...Array(product.countInStock).keys()].map((x) => (
<option key={x + 1} value={x + 1}>
{x + 1}
</option>
))}
</select>
</p>
<p>
<button type="button" onClick={addToCartHandler}>
Add To Cart
</button>
</p>
</div>
</div>
</>
)}
</div>
);
};
export default ProductScreen;

Nothing here is an obsolete style that "does not work any more" - if something doesn't work, it's not because of something being discontinued.
In this explicit case you should probably write something like
// change this
{cartItems.length === 0 ? (
// to this
{!cartItems || cartItems.length === 0 ? (
But generally, you are right, this is an outdated style of Redux and you will probably end up writing multiple times the amount of code than you would need to write if you were writing modern code. Modern Redux does not use switch..case reducers, ACTION_TYPES, you will not dispatch actions as objects directly etc. etc.
Please do yourself a favor and follow the official Redux tutorial instead and also look for other sources that teach up-to-date knowledge.

Related

useEffect conditional statement are not working

Here I am making a shopping app and I have a working cart in it and below is my code for my cart component and here in cart I want to render order button conditionally for that I have isFound state and first I am getting data from my redux store and then I am checking below in useEffect hook if my list is not empty(list is const where I am storing my redux fetched data) then I will set my state=true and initially it is false but the problem is that useEffect is chanigng state to true if there is nothing inside of my list const means even if cart is empty and even though I am setting useEfect dependency proprly as well but it is showing order button all the time so someone can please help thanks:
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import classes from "./Cart.module.css";
const Cart = () => {
const navigate = useNavigate();
const [isFound, setIsFound] = useState(false);
const orders = useSelector((state) => state.data.DUMMY_DATA);
const list = orders.map(
(data, key) =>
data.product_count > 0 && (
<div className={classes.wrapper}>
<div className={classes.item}>
Item:   {data.product_name}{" "}
</div>
<div className={classes.amount}>
Amount:   {data.product_count}{" "}
</div>
<div className={classes.price}>
Price:   {data.product_price}
</div>
</div>
)
);
useEffect(() => {
if (list !== "") {
setIsFound(true);
}
}, [list]);
return (
<div className={classes.modal}>
<div className={classes.root}>
<span
className={classes.close}
onClick={() => navigate("/", { replace: true })}
>
×
</span>
{list}
{isFound && (
<div className={classes.order_button_wrapper}>
<button className={classes.order_button}>Order</button>
</div>
)}
</div>
</div>
);
};
export default Cart;
.map alway return an array. So list !== "" will alway be true.
Here is useEffect, you have an array not a string as list value:
useEffect(() => {
if (list.length > 0) {
setIsFound(true);
}
}, [list]);
You have placed a watcher on the list variable, that's why useEffect is not calling, you need to place a watcher on the state because the state is being rendered and when any changes to the state useEffect will be called, variable is not rendered That's is why useEffect is not being called and changes to your component are not being replicated. You have to create a state and put the list value in the state and you have to call the function in the useEffect because you only have one called otherwise your function will be calling, as you code below can see.
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import classes from "./Cart.module.css";
const Cart = () => {
const navigate = useNavigate();
const [isFound, setIsFound] = useState(false);
const orders = useSelector((state) => state.data.DUMMY_DATA);
const [ordersList, setOrdersList] = useState("");
useEffect(() => {
const list = orders.map(
(data, key) =>
data.product_count > 0 && (
<div className={classes.wrapper}>
<div className={classes.item}>
Item:   {data.product_name}{" "}
</div>
<div className={classes.amount}>
Amount:   {data.product_count}{" "}
</div>
<div className={classes.price}>
Price:   {data.product_price}
</div>
</div>
)
);
setOrdersList(list);
}, [])
useEffect(() => {
if (ordersList !== "") {
setIsFound(true);
}
}, [ordersList]);
return (
<div className={classes.modal}>
<div className={classes.root}>
<span
className={classes.close}
onClick={() => navigate("/", { replace: true })}
>
×
</span>
{ordersList}
{isFound && (
<div className={classes.order_button_wrapper}>
<button className={classes.order_button}>Order</button>
</div>
)}
</div>
</div>
);
};
export default Cart;

How can I default category through api

I have written a project which receives data through an api. Clicking on each button displays corresponding news. For example, when you press the sports button, sports news comes. However, I want the All category to be active when the page is first opened. In other words, those news should have arrived without pressing the all button. How can I do this?
Not - The function inside useffect returns every time it renders and it doesn't work for me. For example, when you refresh the page while reading sports news, all news comes
import React, { useEffect, useState } from "react";
import SpinnerLoad from './components/SpinnerLoad'
import NewsItem from "./components/NewsItem";
import Category from "./components/data/Category"
const App = () => {
const [state, setState] = useState([]);
const [loading, setLoading] = useState(false)
const fetchValue = (category) => {
fetch(`https://inshorts-api.herokuapp.com/news?category=${category}`)
.then(res => res.json())
.then(res => {
setState(res.data)
setLoading(true)
})
.catch((error) => console.log(error))
setLoading(false);
};
const CategoryButton = ({ category }) => (
<button onClick={() => fetchValue(category)} style={{ textTransform: 'capitalize' }}>{category}</button>
);
useEffect(() => {
fetchValue('all')
}, [])
return (
<>
<div className="header-bg">
<h1 className="mb-3">News</h1>
<div className="btns ">
{Category.map((value, index) => {
return <CategoryButton category={value} key={index} />;
})}
</div>
</div>
<div className="news">
<div className="container">
<div className="row">
{
!loading
? <SpinnerLoad/>
:
state.map((data,index) => {
return (
<NewsItem
imageUrl={data.imageUrl}
author={data.author}
title={data.title}
content={data.content}
date={data.date}
key={data.id}
/>
);
})
}
</div>
</div>
</div>
</>
);
};
export default App;
import React from 'react'
import clock from "../components/assets/img/Clock.svg"
import user from "../components/assets/img/User.svg"
const NewsItem = (props) => {
const {imageUrl, title, content, date, author} = props
return (
<div class="col-lg-4 col-md-6 col-12 p-2">
<div className="newsItem">
<img src={imageUrl} alt=''/>
<div className="itemBody">
<p className='title'>{title}</p>
<div className="line"></div>
<p className='content'>{content}</p>
<div className="itemfooter">
<h6><img src={clock} alt='clock'/>{date}</h6>
<h6><img src={user} alt='user'/>{author}</h6>
</div>
</div>
</div>
</div>
)
}
export default NewsItem
In react, if you refresh the app , the state values will reinitialise.
From your question , it seems like you want to store the category value and even after refresh , you want to persist the category value..
For that you can store category value in local or sessionStorage..
const fetchValue = (category) => {
localStorage.setItem("category", category);
// your code
}
// in useEffect , you can check for the category value in the local Storage
useEffect(() => {
// check value in localStorage, if does not exist use "all" as default value
let categoryValue = localStorage.getItem("category") || "all" ;
fetchValue(categoryValue)
},[]);

Content disappears after page refresh

I have a problem with my react app. I have a blog page where I can create blog posts and display them to the screen. In this part everything works fine. User logs in and can write a post. Each post contains a Read more... link and if the user clicks on that link the app redirects to the actual blog post. There the user can read the whole blog and add some comments. Everything works perfectly except when the user refreshes the page, everything disappears without any error in the console. I use firebase as my back-end and everything is saved there just like it has to be. Each time I click on the particular post I get redirected to that post and everything is ok, but when I refresh the page everything disappears, the post, the comments, even the input field and the submit comment button.
Here is a picture before refresh:
Before
here is a picture after refresh:
After
Also I will include the code for the actual blog and comment section.
The BlogAndCommentPage contains the actual blog post and holds the input field for the comments and the comments that belong to this post.
import React from 'react'
import { projectFirestore } from '../../firebase/config';
import BackToBlogs from './BackToBlogs'
import AddComment from '../commentComponents/AddComment'
class BlogAndCommentPage extends React.Component {
state = { param: '', blog: [] }
componentDidMount = () => {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString)
const id = urlParams.get('id')
this.setState({ param: id })
const fetchDataFromFireBase = async () => {
projectFirestore.collection('Blogs').doc(id).get()
.then(doc => {
if(doc.exists) {
let document = [];
document.push(doc.data());
this.setState({ blog: document })
}
})
}
fetchDataFromFireBase()
}
renderContent() {
// Display the blog
const blogs = this.state.blog?.map(value => {
return (
<div key={value.post.blogID}>
<h1>{value.post.title}</h1>
<h6>{`${value.post.name} - ${value.post.date}`}</h6>
<p>{value.post.body}</p>
</div>
)
})
return blogs;
}
render() {
const displayedBlog = this.state.param
return (
<div>
{
displayedBlog ? (
<div>
{this.renderContent()}
<BackToBlogs />
<hr></hr>
<h5 className="mb-2">Add a comment</h5>
<AddComment param={this.state.param} />
</div>
) : ''
}
</div>
)
}
}
export default BlogAndCommentPage
The AddComment component holds the submit button for the comments and the list of the components
import React, { useState, useEffect } from 'react'
import SubmitComment from './SubmitComment'
import CommentHolder from './CommentHolder';
import { useSelector, useDispatch } from 'react-redux';
const AddComment = ({ param }) => {
const [comment, setComment] = useState('');
useEffect(() => {
if (sessionStorage.getItem('user') === null) {
alert('You are not logged in. Click OK to log in.')
window.location = 'http://localhost:3000/'
}
}, [])
const dispatch = useDispatch();
const state = useSelector((state) => state.state);
if (state) {
setTimeout(() => {
setComment('')
dispatch({ type: "SET_FALSE" })
}, 50)
}
return (
<div>
<div>
<div className="row">
<div className="col-sm">
<div className="form-group">
<textarea rows="4" cols="50" placeholder="Comment" className="form-control mb-3" value={comment} onChange={(e) => setComment(e.target.value)} />
</div>
</div>
</div>
</div>
<div className="mb-3">
<SubmitComment comment={comment} param={param} />
</div>
<CommentHolder param={param} />
</div>
)
}
export default AddComment
The CommentHolder renders each comment that belong to that post
import React from 'react';
import { projectFirestore } from '../../firebase/config';
import DeleteComment from './DeleteComment'
class CommentHolder extends React.Component {
state = { docs: [] }
_isMounted = false;
componentDidMount = () => {
const fetchDataFromFireBase = async () => {
const getData = await projectFirestore.collection("Comments")
getData.onSnapshot((querySnapshot) => {
var documents = [];
querySnapshot.forEach((doc) => {
documents.push({ ...doc.data(), id: doc.id });
});
if (this._isMounted) {
this.setState({ docs: documents })
}
});
}
fetchDataFromFireBase()
this._isMounted = true;
}
componentWillUnmount = () => {
this._isMounted = false;
}
renderContent() {
// Delete comments
const deleteComment = async (id) => {
projectFirestore.collection('Comments').doc(String(id)).delete().then(() => {
console.log(`Blog with id: ${id} has been successfully deleted!`)
})
}
// Build comments
let user;
if (sessionStorage.getItem('user') === null) {
user = [];
} else {
user = JSON.parse(sessionStorage.getItem('user'));
const commentArray = this.state.docs?.filter(value => value.blogID === this.props.param)
.sort((a, b) => (a.time > b.time) ? -1 : (b.time > a.time) ? 1 : 0)
.map(comment => {
return (
<div key={comment.id} className="card mb-3" >
<div className="card-body">
<div className="row">
<div className="col-sm">
<h6>{`${comment.name} - ${comment.time}`}</h6>
<p>{comment.comment}</p>
</div>
<div className="col-sm text-right">
{user[0].id === comment.userID ? <DeleteComment commentid={comment.id} onDeleteComment={deleteComment} /> : ''}
</div>
</div>
</div>
</div>
)
});
const updateComments = () => {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString)
const id = urlParams.get('id')
const updateComment = projectFirestore.collection('Blogs').doc(id);
return updateComment.update({
'post.comments': commentArray.length
})
}
updateComments()
return commentArray;
}
}
render() {
return (
<div>
{this.renderContent()}
</div>
)
}
}
export default CommentHolder
The DeleteComment deletes the comment
import React from 'react'
const DeleteComment = ({ commentid, onDeleteComment }) => {
return (
<div>
<button onClick={() => onDeleteComment(commentid)} className='btn btn-outline-danger'>X</button>
</div>
)
}
export default DeleteComment
The SubmitComment stores the comment in the Firebase
import React from 'react'
import { projectFirestore } from '../../firebase/config';
import { v4 as uuidv4 } from 'uuid';
import { useDispatch } from 'react-redux';
const SubmitComment = ({ comment, param }) => {
const dispatch = useDispatch();
const onCommentSubmit = () => {
let user;
if (sessionStorage.getItem('user') === null) {
user = [];
} else {
user = JSON.parse(sessionStorage.getItem('user'));
projectFirestore.collection('Comments').doc().set({
id: uuidv4(),
comment,
name: `${user[0].firstName} ${user[0].lastName}`,
userID: user[0].id,
blogID: param,
time: new Date().toLocaleString()
})
dispatch({ type: "SET_TRUE" });
}
}
return (
<div>
<button onClick={() => onCommentSubmit()} className='btn btn-primary'>Add comment</button>
</div>
)
}
export default SubmitComment
In case there is a rout problem here is the code for the routing between the blogs section and the blog + comments section
return (
<Router >
<Route path='/content-page' exact render={(props) => (
<>
<BlogAndCommentPage />
</>
)} />
<Route path='/blogpage' exact render={(props) => (
<>
<div>
<div className="row">
<div className="col-8">
<h1 className='mb-3'>Blog</h1>
</div>
<div className="col-4 mb-3">
<LogoutButton onLogOut={logout} />
<h6 className='float-right mt-4 mr-2'>{displayUser}</h6>
</div>
</div>
{empty ? (<div style={{ color: "red", backgroundColor: "#F39189", borderColor: "red", borderStyle: "solid", borderRadius: "5px", textAlign: 'center' }} className="mb-2">Title and body cannot be blank</div>
) : ("")}
<InputArea getBlogContent={getBlogContent} />
<CreateBlog post={post} onCheckEmptyInputs={checkEmptyTitleAndBody} />
<hr />
<BlogHolder />
</div>
</>
)} />
</Router>
)
If anybody has any clue on why is this happening, please let me know.
Thank you.
As your website is CSR (client side rendering) it doesn't understand the URL in the first execution, you might need to configure a hash router, take a look at:
https://reactrouter.com/web/api/HashRouter
Also, there is a good answer about it here

Pass props to component: "Objects are not valid as a React child"

I'm trying to simply pass the Id of a clicked item to display on another page under a different component ("Cart") . At the bottom of the code below, I have a button containing <Cart test={product.id} /> which extracts the Id that I want to be displayed in "Cart" when the button is clicked.
However, I am instead getting an error message of:
Objects are not valid as a React child (found: object with keys
{history, location, match, staticContext}). If you meant to render a
collection of children, use an array instead.
Is there a simple syntax error?
import React, { useState, useEffect, Cart } from 'react';
import './../App.css';
import * as ReactBootStrap from 'react-bootstrap';
function Item(props) {
const [product, setProduct] = useState([]);
const [loading, setLoading] = useState(false);
const [quantity, setQuantity] = useState(1);
const [cost, setCost] = useState([]);
useEffect(async () => {
fetchItems();
}, []);
const itemId = props.match.params.item;
const fetchItems = async () => {
const data = await fetch('https://fakestoreapi.com/products/' + itemId);
const items = await data.json();
setProduct(items);
setLoading(true);
setCost(items.price);
};
function priceUSD(change) {
return change.toFixed(2);
}
useEffect(() => {
const newCost = quantity * product.price;
setCost(priceUSD(newCost));
}, [quantity]);
return (
<div className="App">
<h2>Item</h2>
<div className="gridContainer">
{loading ? (
<div key={itemId} className="productStyle">
<img src={product.image} className="productImage"></img>
<p>{product.title}</p>
<p>{product.description}}</p>
<p>${priceUSD(product.price)}</p>
<div className="quantity">
<button
className="btn minus-btn"
type="button"
onClick={quantity > 1 ? () => setQuantity(quantity - 1) : null}
>
-
</button>
<input type="text" id="quantity" value={quantity} />
<button className="btn plus-btn" type="button" onClick={() => setQuantity(quantity + 1)}>
+
</button>
</div>
<button type="button" onClick={() => <Cart test={product.id} />}>
Add to shopping cart ${cost}
</button>
</div>
) : (
<ReactBootStrap.Spinner className="spinner" animation="border" />
)}
</div>
</div>
);
}
export default Item;
Cart
import React, { useState, Item } from 'react';
import './../App.css';
import './Item.js';
function Cart(test) {
return (
<div className="App">
<p>{test}</p>
</div>
);
}
export default Cart;
Component props are objects. You can read more about them in the official documentation.
You can either destructure the props of the Cart component:
function Cart({test}) {
return (
<div className="App">
<p>{test}</p>
</div>
);
}
or use explicitly test property of props:
function Cart(props) {
return (
<div className="App">
<p>{props.test}</p>
</div>
);
}

React - Simplifying the code inside the return

The following code shows a list of 10 users (list-view) and if you click on Details button of any of those users, it shows only that particular user (user-view).
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const UserList = ({ id, setID }) => {
const [resources, setResources] = useState([])
const fetchResource = async () => {
const response = await axios.get(
'https://api.randomuser.me/?results=10'
)
console.log(response.data.results)
setResources(response.data.results)
}
useEffect(() => {
fetchResource()
}, [])
return (
<ul className='card__wrapper'>
{resources.filter(user => (id) ? user.login.uuid === id : true)
.map(item => (
<li className='card' key={item.name.first}>
<div className='card__item'>
<img className='card__image' src={item.picture.large} alt={item.name.first} />
<h2 className='card__title'>{item.name.first} {item.name.last}</h2>
{
id
?
<button
className='card__cta'
onClick={() => setID(null)}
>
Back to overview
</button>
:
<button
className='card__cta'
onClick={() => setID(item.login.uuid)}
>
Details
</button>
}
</div>
</li>
))}
</ul>
)
}
export default UserList
While this is working fine, the code inside the return which builds both the list-view and also the user-view is a bit difficult to understand (at least for me) and also makes it hard for using different CSS classes for List- and User-view.
I'd like to simplify the code so that's easier to understand by splitting it to two different returns.
Basically, saying that if the condition is true, return the user-view otherwise the list-view
How can I do that?
I would put the rendering stuff into another function, and to make what is going to be clearer I would use two returns:
import React, { useState, useEffect } from "react";
import axios from "axios";
const UserList = ({ id, setID }) => {
const [resources, setResources] = useState([]);
const fetchResource = async () => {
const response = await axios.get("https://api.randomuser.me/?results=10");
console.log(response.data.results);
setResources(response.data.results);
};
useEffect(() => {
fetchResource();
}, []);
const renderItem = (item, isLoggedIn) => {
return (
<li className="card" key={item.name.first}>
<div className="card__item">
<img className="card__image" src={item.picture.large} alt={item.name.first} />
<h2 className="card__title">
{item.name.first} {item.name.last}
</h2>
{isLoggedIn ? (
<button className="card__cta" onClick={() => setID(null)}>
Back to overview
</button>
) : (
<button className="card__cta" onClick={() => setID(item.login.uuid)}>
Details
</button>
)}
</div>
</li>
);
};
const user = resources.find(user => user.login.uuid === id);
if (user) {
return <ul className="card__wrapper">{renderItem(user, true)}</ul>;
} else {
return <ul className="card__wrapper">{resources.map(user => renderItem(user, false))}</ul>;
}
};
export default UserList;
Looks like the question asked pertains to this React hooks - OnClick show only the clicked item
Please find my comment for the above post, as I guess this particular issue can be solved as mentioned in the comment! In case it doesn't fix, let me know.

Resources