У меня проблема с отображением, которую я не могу исправить. В моем приложении у меня есть компонент Posts
, состояние которого содержит массив данных сообщений.
[
{ id: "P01", title: "First post", likeCount: 0 },
{ id: "P02", title: "Second post", likeCount: 0 }
]
В этом компоненте я отображаю состояние posts
, чтобы вернуть компонент Post
для каждое сообщение внутри состояния сообщений.
Компонент сообщений
export default function Posts() {
const [posts, setPosts] = useState(null);
const fetchPosts = () => {
setPosts([
{ id: "P01", title: "First post", likeCount: 0 },
{ id: "P02", title: "Second post", likeCount: 0 }
]);
};
const handleLike = (id) => {
setPosts(
posts.map((post) =>
post.id === id ? { ...post, likeCount: post.likeCount + 1 } : post
)
);
};
return (
<div>
<button onClick={fetchPosts}>Fetch posts</button>
{posts !== null ? (
posts.map((post, index) => {
return <Post key={index} post={post} handleLike={handleLike} />;
})
) : (
<p>No post to dipslay</p>
)}
</div>
);
}
Компонент сообщения
function Post({ post, handleLike }) {
console.count("Renders for: " + post.id);
return (
<div>
<h1>{post.title}</h1>
<p>Like count: {post.likeCount}</p>
<button onClick={() => handleLike(post.id)}>Like</button>
</div>
);
}
export default React.memo(Post);
Проблема в том, что, когда мне нравится Post
, все другие Post
компоненты повторно визуализируются. Я добавил console.count()
к дочернему компоненту Post
, чтобы показать это в действии (см. Ниже ссылку на песочницу). Из-за этого у меня проблема с производительностью, потому что в моем приложении у меня есть много сообщений для отображения с большим количеством дочерних компонентов.
Я пытался обернуть компонент Post
, используя React.memo
, но он все еще выполняет повторный рендеринг компонента, потому что функция handleLike
, переданная компоненту в качестве свойств, также изменилась при повторном рендеринге Posts
. Возможно, можно избежать этой проблемы с рендерингом с помощью хуков useMemo / useCallback
, но я не знаком с ними и не могу заставить их работать так, как я хочу.
Какие у меня здесь варианты?
Здесь вы можете найти упрощенный демонстрационный код: https://codesandbox.io/s/re-render-issue-esm01