Search code examples
javascriptreactjslisthighlight

Highlight One Item in a List at any given time (Index 0 by default)


Sorry for the horrible title, I couldn't for the life of me figure out how to word this problem. By default I want the first item in my list to be highlighted and others to be highlighted when the mouse is over them. This works fine and I was curious how I am able to remove the highlight of that initial item when another is highlighted, I know I need to handle the state within my parent component (List) but I cannot figure it out.

This is my list item that contains some basic state management to show whether the given item is highlighted or not.

export default function Item ({ title, onClick, selected, i }) {
  const [highlight, setHighlight] = useState(false)

  return (
    <ListItem
      i={i}
      key={title}
      selected={selected}
      onClick={onClick}
      onMouseEnter={() => setHighlight(true)}
      onMouseLeave={() => setHighlight(false)}
      // i === 0 && no other item is highlighted (need to get this state from the list component)
      highlight={highlight || i === 0}
    >
      {title}
    </ListItem>
  )
}

Parent component that takes in a 'list' and maps each item in that list to the above component (Item):

export default function List ({ list, onClick, selected, render }) {s
  return (
    <div>
      {render ? (
        <ListContainer>
          {list.map((item, i) => (
            <Item
              i={i}
              key={item.title}
              title={item.title}
              onClick={() => onClick(item.title)}
              selected={selected(item.title)}
            />
          ))}
        </ListContainer>
      ) : null}
    </div>
  )
}

Here is a Gyazo link that shows the current implementation, what I want to achieve is for that initial item to no longer be highlighted when the mouse has entered another item where the index does not equal 0.


Solution

  • You need to lift your highlight state to parent List component

    function List ({ list, onClick, selected, render }) {
      const [highlightIndex, setHighlightIndex] = setState(0);
      return (
        <div>
          {render ? (
            <ListContainer>
              {list.map((item, i) => (
                <Item
                  i={i}
                  key={item.title}
                  title={item.title}
                  onClick={() => onClick(item.title)}
                  selected={selected(item.title)}
                  highlightIndex={highlightIndex}
                  setHighlightIndex={setHighlightIndex}
                />
              ))}
            </ListContainer>
          ) : null}
        </div>
      )
    }
    
    function Item ({ title, onClick, selected, i, highlightIndex, setHighlightIndex }) {
      return (
        <ListItem
          i={i}
          key={title}
          selected={selected}
          onClick={onClick}
          onMouseEnter={() => setHighlightIndex(i)}
          highlight={i === highlightIndex}
        >
          {title}
        </ListItem>
      )
    }