Home > Mobile >  toggle boolean in react needed, but not quite sure
toggle boolean in react needed, but not quite sure

Time:02-01

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>
    </>
  );
}
  • Related