skip to Main Content

How can I sort my shopping list? I have the code as addSort function. Everything looks good to me not sure what im doing wwrong. I can’t get it to work. I would like when the user selects the dropdown they can select the option of Alphabetical or list added order. I have the ddropdown working. The function looks right but I can’t get it to work.

import logo from './logo.svg';
import './App.css';
import { useState, useRef } from 'react';
import classes from './ChoreList.module.css';
// maintain state by importing the usestate

//Possible user actions to events:
//Delete an element
//Mark or unmark as done
// add an element (chore)


  //list of elementswith array of items with unique ids
  //three attribute for each one of the objects 
// Possible user actions to events:
//     delete an element
//     mark or unmark as done (possibly with a checkbox)
//     add an element (chore)
//

const elements = [
  {
    id: 1,
    item: "Cucumber",
    done: true
  }
];

function ChoreList(props) {

  const { items, handleDelete, handleCheck, ...my_props } = props;

  // function clickEvent(my_event) {
  //   my_event.preventDefault();
  //   handleDelete(my_event, );
  // }

  return (
    <ul className='myList'>
      {items.map(element => <li id={element.id} key={element.id}>
        <input type='checkbox' 
        checked={element.done} 
        onChange={evt => handleCheck(evt, 
        element.id)}>
        </input> 
      <span className={element.done ? classes.done : classes.notdone }>{element.item}</span> 
      (<a href='null' onClick={(evt) => handleDelete(evt, element.id)}>Remove</a>)</li>)}
    </ul>
  )
} 

function Summary(props) {

  // const { items } = props;
  // items.length  would then refer to the number of item

  return (
    <div className='b-bottom'>{props.items.length} items</div>
  )
}

function AddElement(props) {

  const { addItem, addRef } = props;
  return (
    <div className='holder'>
      <label htmlFor='newitem' className='label-input'>Add Item</label> 
      <input ref={addRef} type='text' id='newitem' className='form-control' />
      <button onClick={addItem} className='button-t'>Add</button>
    </div>
  )
}


function sortByItem(props) {

}

function AddSort(props) {

  const [ item, setitem ] = useState(elements);

  const sortItem = (selectEvent) => {
    const options = {
      "a-z": [...item].sort((a, b) => a.item > b.item),
      "z-a": [...item].sort((a, b) => (a < b ? 1 : -1))
    };

    setitem(options[selectEvent.target.value]);
  };

  return (
    <div className="dropmenu">
      <select onChange={sortItem}>
        <option value="a-z">Alphabetical</option>
        <option value="z-a">Order Added</option>
      </select>
    </div>
  );

}

function App() {

  const [ item, setitem ] = useState(elements);
  const newChoreRef = useRef();

  function handleDelete(user_event, id) {
      user_event.preventDefault();
      const new_item = item.filter(e => e.id !== id);
      setitem(new_item);
  }

  function handleCheck(user_event, id) {
    console.log("need to change the status of " + id);
    // update state so that done is set to checked (or not)
    console.log(user_event.target.checked);

    // version that uses the ternary operator
    const new_item = item.map(e => (e.id === id) ? 
      {
        id: e.id, 
        item: e.item, 
        done: user_event.target.checked
      } 
      : e);

    // somewhat simpler version
      // const new_item = item.map(e => {
    //   if (e.id == id) {
    //     return {
    //       id: e.id,
    //       item: e.item,
    //       done: user_event.target.checked
    //     }
    //   }
    //   else {
    //     return e;
    //   }
    // });

    // original version
    // const new_item = item.map(e => {
    //   if (e.id == id) {
    //     return {
    //       id: e.id,
    //       item: e.item,
    //       done: user_event.target.checked
    //     }
    //   }
    //   else {
    //     return {
    //       id: e.id,
    //       item: e.item,
    //       done: e.done
    //     }
    //   }
    // });

    setitem(new_item);
  }

  function addItem(evt) {

    const choreDescription = newChoreRef.current.value;
    const newchore = {
      id: item.length + 1,   // it would be better to keep a state that incremented the id
      item: choreDescription,
      done: false
    }
    const new_item = item.concat([newchore]);

    setitem(new_item);
  }

  return (
    <>
      <div className='shoplist-holder'>
        <div className='header-holder'>
          <div className='header-col'>
            <div className='header'><h1>Sams Shopping List</h1></div>
            <Summary items={item}></Summary>
          </div>
          <div className='sub-header'><AddSort items={item}></AddSort></div>
        </div>
      <AddElement addItem={addItem} addRef={newChoreRef}></AddElement>
      <ChoreList items={item} handleDelete={handleDelete} handleCheck={handleCheck}></ChoreList>
      </div>
    </>
  );
  
}

export default App;

2

Answers


  1. I don’t know what is your problem, but it’s not about sorting.
    Please provide a simple sample when you have issues (it might also help you to realize the issue is not what you think it is)

    In any case, this would work fine :

    const elements = [
      {
        id: 1,
        item: "Cucumber"
      },
      {
        id: 2, 
        item: "Carrots"
      },
      {
        id: 3,
        item: "Zucchinis"
      }
    ];
    
    console.log(elements.sort((a,b) => a.item > b.item ? 1 : -1))
    
    (3) [{...}, {...}, {...}]
    0:(3) {id: 2, item: "Carrots"}
    1:(3) {id: 1, item: "Cucumber"}
    2:(3) {id: 3, item: "Zucchinis"}
    
    Login or Signup to reply.
  2. The list of chores is maintained in state inside the App component, yet you are attempting to sort the list within the AddSort component.

    You need to move the sortItem() method to the App component and pass the method as a prop – just like you do with the handleDelete and handleCheck handlers.

    <AddSort sortItem={sortItem} items={item}></AddSort>

    You may also find it useful to call sortItem() in useEffect() to provide an initial sort too.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search