Реагировать список, показывать активный элемент onClick. Без повторного рендеринга списка

avatar
Navdeep kumar
1 июля 2021 в 20:43
84
1
0

Я хочу отобразить другой стиль для стандартного элемента, по которому щелкнули, но когда я устанавливаю для activeItem значение idx clicked, react снова перерисовывает весь список. Есть ли способ показать только один активный элемент без повторной визуализации списка

import React, { useState,memo} from "react";

const StocksList=({stocksData})=>{

    const [activeItem, setActiveItem] = useState(0);
    
    const Item=({stock,idx})=>{
        return (
            <li 
                className={activeItem===idx ? "active-stock-item" : "stock-item" }
                onClick={()=>{
                    setActiveItem(idx);
                }} 
            >
                {`${idx+1}. ${stock["Name"]}`}
            </li>
        )
    }
    
    return(
        stocksData.map((stock,idx) => <Item key={stock._id} {...{stock,idx}} />)
    )
}

export default memo(StocksList)
Источник
Dani
2 июля 2021 в 20:28
0

Обычно это должно быть хорошо, потому что вы уже добавили ключ к каждому элементу, так что при обновлении реакция не будет повторно отображать весь список, а только те, которые содержат изменения

Ответы (1)

avatar
GAntoine
1 июля 2021 в 20:46
1

Установите key для каждого отображаемого элемента.

stocksData.map((stock,idx) => <Item key={idx} {...{stock,idx}} />)

В качестве примечания рекомендуется не использовать индекс объекта в качестве ключа. Если stock имеет идентификатор или другой уникальный идентификатор, используйте его.

Редактировать

Основываясь на ваших комментариях, вот рабочая версия, которая обновит выбранный активный элемент:

import React, { useState,memo} from "react";

const stocksData = [
  {
    _id: 0,
    name: "Zero"
  },
  {
    _id: 1,
    name: "One"
  }
];

const Item=({ _id, name, active, onClick })=>{
  function onSelfClick() {
    onClick(_id);
  }

  return (
      <li 
          className={active ? "active-stock-item" : "stock-item" }
          onClick={onSelfClick} 
      >
          {`${ _id +1 }. ${name}. ${active}`}
      </li>
  )
}

export default function StocksList() {
    const [activeItem, setActiveItem] = useState(stocksData[0]._id);

    function onClick(id) {
      setActiveItem(id)
    }
    
    return (
        stocksData.map(stock => <Item key={stock._id} active={activeItem === stock._id} onClick={onClick} {...stock} />)
    )
}
ray hatfield
1 июля 2021 в 20:49
2

И, может быть, не определять сам компонент Item внутри рендеринга List? Я ожидаю, что он будет воссоздаваться каждый раз, ключ или нет.

Navdeep kumar
2 июля 2021 в 20:23
0

@rayhatfield, когда я помещаю компонент Item снаружи, реакция не будет повторно отображать список, но выделение каждого только одного элемента не будет работать. Он выделяет каждый элемент, который я нажимаю, я хочу выделить только один элемент.

Navdeep kumar
2 июля 2021 в 20:24
0

@GAntoine, извините, в моем фактическом коде был ключ, я обновил вопрос.

GAntoine
2 июля 2021 в 20:37
0

@Navdeepkumar Я обновил ответ рабочим примером.

Husdady
24 апреля 2022 в 22:56
0

Это хорошее решение @GAntoine