Venkat
Venkat

Reputation: 21

How to move the list item to top when selected in ReactJs

I'm trying the scenario in the ReactJS application like. created dummy data in App.js itself with name and id, crated another component with List.js where displaying the list items.

If I selected any of the list item it should be move the item to top like below before

after

I created function in List.js file but it not working

//----App.js-------
import "./styles.css";
import List from './List'

const data = [
  {id:1,letter:"A"},
  {id:2,letter:"B"},
  {id:3,letter:"C"},
]
export default function App() {
  
  
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <List items={data}/>
    </div>
  );
}


//----List.js-------
import React from 'react';
import {useState} from 'react'

export default function List({items}){
  console.log(items);
  const [selectedIndex,setSelectedIndex] = useState(0)

  const selectList = (items,ind)=>{
    console.log(ind+1);
    
    const arr = Object.entries(items,ind)
    setSelectedIndex(()=>{
      arr.sort((a,b)=>{
        return a.id===ind+1?-1:b.id===ind+1?1:0
      })
    })
    // console.log(items,ind);
    
  }
  
  return(
    <div>
      <ul>
        {/* {console.log(items)} */}
        {items.map((item,ind)=>{
          return(
            <li key={ind} onClick={()=>selectList(item,ind)}>{item.letter}</li>
          )
        })}
      </ul>
    </div>
  )
}

Upvotes: 1

Views: 1941

Answers (2)

yohanes
yohanes

Reputation: 2675

Just try this approach. First create items state that will hold the data.

const [items, setItems] = useState(data);

Next create a reorder function where you pass the clicked id.

const reorder = (id) => {
  ...
}

Inside the function, we declare the first item that the value will be assigned during filtration later.

And then define a filter function where we get the first item by its id, put it inside an array, and assign it to the firstItem variable. The filter iteration process should result in filteredItems (exclude the clicked item).

Then, clone both firstItem and filteredItems by using shallow copy, set as items by using setItems setter.

  const reorder = (id) => {
    let firstItem;
    const filteredItems = items.filter((item) => {
      if (item.id === id) {
        firstItem = [item];
        return false;
      }
      return true;
    });
    setItems([...firstItem, ...filteredItems]);
  };

Then, we can render it like this:

  <ul>
    {items.map((item) => (
      <li onClick={() => reorder(item.id)}>
        {item.letter}
      </li>
     ))}
   </ul>

For example:

Edit silly-grass-gsj34d

Upvotes: 1

Nice Books
Nice Books

Reputation: 1861

Since you need to update the order of the items, it's better to have items as a state property.
To initialize state with props, getDerviedStateFromProps should be used.

class List extends Component {

    constructor(props) {
        super(props);
        this.state = {selectedIndex: 0, items: []};
    }

    static getDerivedStateFromProps(props, state) {
        return {items: props.items};
    }

    selectListItem=(id,ind)=> {
        this.setState((state,props)=> {
            let excludingSelected = state.items.filter((itm,i)=> ind != i);
            return {
                items: [state.items[ind]].concat(excludingSelected), 
                selectedIndex: ind
            };
        }
    }
}

Prefer id as key to index (docs).

Upvotes: 0

Related Questions