I know I need to incorporate a boolean into this, I am just not entirely sure how.
I want to click on the button event and toggle between the data "price" (data.js) put into order of cheapest price and STOP at 5 objects. But then click the same button and return the data to the previous dataspace default
Can anyone help?
App.js
import "./App.css";
import Header from "./Header";
import FeedContainer from "./FeedContainer";
import { useState } from "react";
import FeedData from "./data/data";
function App() {
const [dataspace, setDataspace] = useState(FeedData);
const topFivePrice = () => {
setDataspace([...dataspace].sort((a, b) => (a.price > b.price ? 1 : -1)));
};
return (
<>
<Header />
<div className="container">
<button onClick={topFivePrice}>TOP 5 prices</button>
<FeedContainer dataspace={dataspace} />
</div>
</>
);
}
export default App;
data.js
const FeedData = [
{ name: 'Item A', price: 125, id:1 },
{ name: 'Item B', price: 230, id:2 },
{ name: 'Item C', price: 295, id:3 },
{ name: 'Item D', price: 245, id:4 },
{ name: 'Item E', price: 900, id:5 },
{ name: 'Item F', price: 875, id:6 },
{ name: 'Item G', price: 235, id:7 },
{ name: 'Item H', price: 400, id:8 },
]
export default FeedData
FeedCard.jsx
import React from 'react'
import Card from './components/shared/Card'
import PropTypes from 'prop-types'
function FeedCard({item}) {
// const handleClick = (item) => {
// console.log(item)
// }
return (
<Card >
<div style={{textAlign:'center'}}>
Name : {item.name}<br/>
The Price is £{item.price}
</div>
</Card>
)
}
export default FeedCard
FeedContainer.jsx
import React from 'react'
import FeedCard from './FeedCard'
import Card from './components/shared/Card'
const FeedContainer = ({dataspace}) => {
return (
<div className='feedback-list'>
{dataspace.map((item ) => (
<FeedCard key ={item.id} item={item} />
))}
</div>
)
}
export default FeedContainer
CodePudding user response:
Toggle views
We primarily just need to toggle between a sorted view and the default view. That can be done with a simple boolean state variable to track the current view.
const [isSortedView, setIsSortedView] = useState(false);
// ...
<button onClick={() => setIsSortedView((prev) => !prev)}>TOP 5 prices</button>
Update data view depending on toggle
Then we need to display the correct view to the user depending on the state of the toggle. This is a derived state value, so this is a textbook use-case of the useMemo
hook.
const dataspace = useMemo(() => (
isSortedView
? FeedData
: [...FeedData].sort((a, b) => (a.price > b.price ? 1 : -1)).slice(0,5)
), [isSortedView]);
Avoid resorting every time the user clicks
You also don't need to recalculate the top 5 prices every time the user clicks the button; only when the data changes (which in this app is only on initial load). We can do that with another useMemo
hook.
const top5Prices = useMemo(() => (
[...FeedData].sort((a, b) => (a.price > b.price ? 1 : -1)).slice(0,5)
), []);
Putting it all together
And then the final code updates look like:
function App() {
const [isSortedView, setIsSortedView] = useState(false);
const top5Prices = useMemo(() => (
[...FeedData].sort((a, b) => (a.price > b.price ? 1 : -1)).slice(0,5)
), []);
const dataspace = useMemo(() => (
isSortedView ? FeedData : top5Prices
), [isSortedView]);
return (
<>
<Header />
<div className="container">
<button onClick={() => setIsSortedView((prev) => !prev)}>TOP 5 prices</button>
<FeedContainer dataspace={dataspace} />
</div>
</>
);
}
CodePudding user response:
Like mentioned in the comments this is a good example for using useMemo
.
We create a variable topFiveData
which only updates when dataspace
changes. We add a extra state for the toggle functionality and based on the showTopFivePrice
we decide what data to pass to the FeedContainer
function App() {
const [dataspace, setDataspace] = useState(FeedData);
const [showTopFivePrice, setShowTopFivePrice] = useState(false);
const topFiveData = useMemo(() => {
return [...dataspace]
.sort((a, b) => (a.price > b.price ? 1 : -1))
.slice(0, 5);
}, [dataspace]);
const toggleTopFivePrice = () => {
setShowTopFivePrice((prev) => !prev);
};
return (
<>
<Header />
<div className="container">
<button onClick={toggleTopFivePrice}>TOP 5 prices</button>
<FeedContainer dataspace={showTopFivePrice ? topFiveData : dataspace} />
</div>
</>
);
}