P
P
Phoen1xx2022-01-23 19:45:09
JavaScript
Phoen1xx, 2022-01-23 19:45:09

How to make react redraw only one element when state is updated?

Hello. Please tell me, I create an array of objects in state, and generate child components using map, and when one field changes, everything is re-rendered. Is there any way to optimize this? It seemed to me that this is what the key field is indicated for, but it does not help.
Here is an example code:

let myData = [
    { id: 1, data: 'Foo' },
    { id: 2, data: 'Bar' }
]

export default function Test(){
    let [items, setItem] = useState(myData);

    let setNewItemData = (itemId, data) => {
        let newItems = items.map(item => {
            if(item.id !== itemId){
                return item;
            }

            return { ...item, data }
        });

        setItem(newItems)
    }

    console.log('Render main Component');

    return (
        <>
            {
                items.map(item => {
                    return (
                        <MyItem key={item.id} item={item} setNewItemData={setNewItemData}></MyItem>
                    )
                })
            }
        </>
    )

}

export default function MyItem({ item, setNewItemData }) {
    console.log('Render MyItem');

    return (
        <button onClick={ () => { setNewItemData(item.id, 'New value') } }>{item.data}</button>
    )
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
P
profesor08, 2022-01-23
@Phoen1xx

With each call setNewItemData, you get a new array items. which you shove into setItem. Each time you call setItem, your entire function will be executed, which means that items.map, and each of MyItem. If you want to draw only MyItem, then modify its internal state, and not the state of the parent.

const Item = ({ item }) => {
  const [item, setItem] = useState(itemProp);

  const updateItem = useCallback(() => {
    setItem((item) => ({
      ...item,
      count: item.count + 1
    }));
  }, []);

  return (
    <div onClick={updateItem}>
      {item.title} {item.count}
    </div>
  );
};

V
vItalIyIrtlach, 2022-01-23
@w13vitaliy

When the parent component changes, it renders all child elements

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question