When clicking on a username, I want to display the information individually for that specific user.
I have tried using the handleShow
function, which toggles from false to true, so I can display or hide the content.
The problem is when I click on a user al three divs are displayed and when the show state is false there is no content showing, which is good, but I have a black line coming from the div.
I have tried using display: none on the div, but then when I click on a username, no content is displayed.
What is the solution to display and hide the content only for a specific username and to have a display: none when the show state is false?
export default function App() {
const [data, setData] = useState([]);
const [isLoaded, setIsLoaded] = useState(false);
const [show, setShow] = useState(false);
const handleShow = () => {
setShow((prevShow) => !prevShow);
};
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => {
if (!response.ok) {
throw new Error("Data failed to fetch");
}
return response.json();
})
.then((data) => {
setData(data);
setIsLoaded(true);
});
}, []);
return (
<div className="App">
{isLoaded && (
<>
<Users data={data} handleShow={handleShow} />
<Card data={data[0]} show={show} />
<Card data={data[1]} show={show} />
<Card data={data[2]} show={show} />
</>
)}
</div>
);
}
const Users = (props) => {
const { data, handleShow } = props;
return (
<div>
<p style={{ cursor: "pointer" }} onClick={handleShow}>
{data[0].name}
</p>
<p style={{ cursor: "pointer" }} onClick={handleShow}>
{data[1].name}
</p>
<p style={{ cursor: "pointer" }} onClick={handleShow}>
{data[2].name}
</p>
</div>
);
};
export default Users;
const Card = (props) => {
const { data, show } = props;
return (
<div style={{ border: "1px solid black", textAlign: "center" }}>
{show && (
<>
{" "}
<h3>{data?.id}</h3>
<h3>{data?.username}</h3>
<h3>{data?.email}</h3>{" "}
</>
)}
</div>
);
};
export default Card;
5
Answers
Don’t render anything if your
show
isfalse
. Black line is shown because of the border.You need to extend your state to not only capture whether any user is shown but the selected index (-1 if no user shown). So
handleShow
should get a parameter for the index as well.The
Card
component should not know whether it is shown or not but you should embed theCard
component only when a user is selected (i.e. selected index >= 0). When selected index is -1, output noCard
component and if a user is selected embed just one. Pass the data of the user to show.When you set "show", all your Card-Elements get the new value in the next render. So all Cards are always shown or not shown. You should instead give each card an index and set the Show-Variable to the index, that should be shown. If the index is -1 or null, no card is shown at all.
To achieve this, you could map your array to the Cards:
Side note: When you set states with arrays or objects, you should always create a new instance to avoid side effects. So if you set your data-array, do it like this:
You can take the state "
show
" to a higher level inApp
component like this:Then when
show
isfalse
the component will not be displayed in its entirety.