I have 1 parent(Container) and 2 (List, SelectedItem) child components, Initially I render all data to Container and send all data to list and first item as selectedItem to selected Item component. So ar so good
When a user clicks an item in the List component, it updates the selected item of the Parent through a function, the parent is able to update state, But it is not re-rendering selected item component.
List Component:
import "./SelectedImage.css"
function ListSection({items, updateSelectedItem}) {
return (
<div className="list-section">
<ul>
{
(items).map((item) => {
return <li key={item.id} onClick={() => updateSelectedItem(item.id)}>{item.name}</li>
})
}
</ul>
</div>
);
}
export default ListSection;
Container Component
import LeftSection from './LeftSection';
import logo from './logo.svg';
import RightSection from './RightSection ';
import SelectedItem from './SelectedItem';
import "./App.css";
import ListSection from './ListSection';
import { Component, useState } from 'react';
const products = [
{id: 1, name: "Lime", size: ["large", "medium", "small"], category: "Juice", image: "lime-juice.jpg"},
{id: 2, name: "Orange", size: ["large", "medium", "small"], category: "Juice", image: "orange-juice.jpg"},
{id: 3, name: "Mango", size: ["large", "medium", "small"], category: "Juice", image: "mango-juice.jpg"},
]
function Container() {
let [selectItem, setSelectItem] = useState(products[0]);
function chooseSelectedItem(id) {
let item = products.filter((value) => {
console.log(value.id);
return (value.id == id)
})
setSelectItem(item[0]);
console.log(item[0]);
}
return (
<div className="Container">
<ListSection items={products} updateSelectedItem={chooseSelectedItem}/>
<SelectedItem CurrentSelectedItem={selectItem}/>
</div>
);
}
export default Container;
SelectedItemComponent
import QuantityBar from "./QuantityBar";
import "./SelectedImage.css"
import { useState } from "react";
function SelectedItem({CurrentSelectedItem}) {
let [item, setItem] = useState(CurrentSelectedItem);
return (
<div className="selected-item">
{/* <img src={item.image} className="selected-image" /> */}
{item.name}
{/* <QuantityBar itemCount={0} /> */}
</div>
);
}
export default SelectedItem;
2
Answers
From your code, it seems your
SelectedItem
component is being rerendered (as you could assess by placing a console.log statement in the component), but the selected item is being cached by your useState:The first argument of useState is the initial value; this value is only read on the initial render (i.e. when the component is mounted). Any rerenders afterwards will not update the value of
item
. Since you’re reading the state’s value in{item.name}
, you’ll always see the initial value. If you replace that line with{CurrentSelectedItem.name}
(and maybe remove that useState), you will start seeing new value when an item is selected.Since you’re initializing the state using
useState
with the propCurrentSelectedItem
, any changes toCurrentSelectedItem
won’t be reflected in the state of the component.You can use the
useEffect
hook to update the state ofSelectedItem
wheneverCurrentSelectedItem
changes:Or if
SelectedItem
is solely dependent onCurrentSelectedItem
, you can remove the local state inSelectedItem
and directly useCurrentSelectedItem
as a prop, like