Image de l'article 'Caveat about destructuring Vue props'

Caveat about destructuring Vue props

Destructuring objects in JavaScript is a really cool feature. Using it along with Vue can, however, take on a spin… Let’s dive into one caveat on the topic.

I will explain my use case: I had a PostList component on a forum application. I used this component is two places:

  • one needed the posts to be ordered in the ascending order,
  • the other needed the contrary.

While working on that, I declared my props this way:

1
2
3
4
5
6
7
8
interface PostListProps {
  posts: Post[];
  orderBy: OrderByDirection;
}

const { posts, orderBy } = withDefaults(defineProps<PostListProps>(), {
  orderBy: OrderByDirection.Asc,
});

Then, I used a computed to order the posts as needed:

1
2
3
4
5
6
7
8
const orderedPosts = computed(() => {
  if (orderBy === OrderByDirection.Asc) {
    return posts;
  }
  return [...posts].sort((first, next) =>
    first.publishedAt! < next.publishedAt! ? 1 : -1
  );
});

When I went to test this code, adding a new post worked but it didn’t show in the list.

Using Vue DevTools, I saw the Pinia state updating and the parent component of PostList component did provide the full list…

Why didn’t the new post appear?

Destructuring the props object broke the reactivity and computed requires a reactive dependency!

So the valid code became:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cgit onst props = withDefaults(defineProps<PostListProps>(), {
  orderBy: OrderByDirection.Asc,
});
const orderedPosts = computed(() => {
  if (props.orderBy === OrderByDirection.Asc) {
    return props.posts;
  }
  return [...props.posts].sort((first, next) =>
    first.publishedAt! < next.publishedAt! ? 1 : -1
  );
});

Destructuring is great, but with Vue, use it carefully, especially with computed 🙂.

Credit: Photo by Scott McNiel on Pexels.

License GPLv3 | Terms
Built with Hugo
Theme Stack designed by Jimmy