Не храните выбранный post отдельным состоянием: вычисляйте его из selectedId. Добавьте key, типы props, alt и клавиатурно доступную кнопку вместо кликабельного div.
Обзор кода компонентов App.tsx и Post.tsx
Не храните выбранный post отдельным состоянием: вычисляйте его из selectedId. Добавьте key, типы props, alt и клавиатурно доступную кнопку вместо кликабельного div.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо выполнить ревью исходных файлов App.tsx и Post.tsx.
// App.tsx
import React, { useEffect, useState } from "react";
import "./index.css";
import PostComponent from "./Post";
export default function App() {
const posts_list = [
{
id: "1",
name: "siberia can code 📘",
imagesrc: "https://avatars.githubusercontent.com/u/45297354?v=4",
text: "first post"
},
{
id: "2",
name: "theo",
imagesrc: "https://avatars.githubusercontent.com/u/6751787?v=4",
text: "second post"
},
{
id: "3",
name: "dan abramov",
imagesrc: "https://avatars.githubusercontent.com/u/810438?v=4",
text: "third post"
}
];
const [selectedId, setPostId] = React.useState(0);
const [post, setSelectedPost] = React.useState(posts_list[0]);
console.log("@", selectedId);
useEffect(() => {
setSelectedPost(posts_list[selectedId]);
}, [selectedId]);
return (
<div className="App">
<div>выбранный пользователь:</div>
<div className="user">
<img
className={"avatar"}
src={post.imagesrc}
style={{ width: "30px" }}
/>
{post.name}
</div>
<br />
<br />
<br />
<div>список постов</div>
{posts_list.length
? posts_list.map((el, index) => (
<PostComponent data={el} onClick={() => setPostId(index)} />
))
: []}
</div>
);
}
// Post.tsx
const Posts = ({ data, onClick }: any) => {
const IMAGE = data.imagesrc;
return (
<div className="post" onClick={onClick}>
<img className={"avatar"} src={IMAGE} style={{ width: "30px" }} />
{data.name}
<p>{data.text}</p>
</div>
);
};
export default Posts;
Ответ
Не храните выбранный post отдельным состоянием: вычисляйте его из selectedId. Добавьте key, типы props, alt и клавиатурно доступную кнопку вместо кликабельного div.
Вынесите постоянный posts_list за App и храните реальный ID, а не индекс:
type Post = { id: string; name: string; imagesrc: string; text: string };
const [selectedId, setSelectedId] = useState(posts_list[0]?.id ?? null);
const post = posts_list.find(item => item.id === selectedId);
// В JSX:
{post && <div className="user">
<img className="avatar" src={post.imagesrc} alt="" width={30} />{post.name}
</div>}
{posts_list.map(item => <PostComponent key={item.id} data={item}
onClick={() => setSelectedId(item.id)} />)}
Post.tsx:
type Props = { data: Post; onClick: () => void };
export default function PostComponent({ data, onClick }: Props) {
return <button type="button" className="post" onClick={onClick}>
<img className="avatar" src={data.imagesrc} alt="" width={30} />
<span>{data.name}</span><span>{data.text}</span>
</button>;
}
Общий тип Post экспортируйте из файла типов. Удалите эффект синхронизации и лишние импорты. Для отступов используйте CSS вместо цепочки br. Защита post от undefined нужна при пустом или изменившемся списке.