$derived и работа с состояниемИ снова здравствуйте 🤔
Не отвлекаясь от подготовки к новогодним праздникам рассмотрим одну руну, которая позволяет довольно комфортабельно взаимодействовать с состоянием приложения
Пока во Vue есть
computed, Svelte же предлагает $derived, что в переводе буквально означает производное состояние от какого-либо другогоКак всегда с примерами жизнь краше, поэтому предположим, что у нас есть список задач, которые нужно получить
🌟Создаем запрос при монтировании компонента и записываем данные в стейт, для этого нам понадобится
onMount и уже известная руна $state:import { onMount } from 'svelte';
let todos = $state([]);
onMount(async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/todos');
todos = await res.json();
});
</script>
🌟Например, нам нужно отфильтровать уже завершенные задачи, чтоб вывести в каком-то отдельном месте, а заодно и посчитать количество всех имеющихся, для этого мы как раз воспользуемся
$derived
let todosLen = $derived(todos.length);
let todosCompleted = $derived(todos.filter(todo => todo.completed));
📌При этом если изменятся исходный стейт
todos, то автоматически изменится и производные todosLen с todosCompletedНо вот клиент внезапно захотел, чтобы в заголовках задач добавлялась приставка
[completed] и [uncompleted], это уже несколько сложнее и потенциально в одну строку не вместится, что делать?Для этого Svelte предлагает
$derived.by, который принимает функцию в качестве аргумента и позволяет выполнять более сложные манипуляции🌟Берем наши
todos, $derived.by и скрещиваем:let tempTodosArray = [];
for (const todo of todos) {
if (todo.completed) {
tempTodosArray = [...tempTodosArray, {
...todo,
title: `${todo.title} [completed]`
}]
} else {
tempTodosArray = [...tempTodosArray, {
...todo,
title: `${todo.title} [uncompleted]`
}]
}
}
return tempTodosArray;
});
И все, клиент доволен, мы справились, а при выводе массив продолжит автоматически пересчитываться, если произойдут какие-то изменения в родительском состоянии
#svelte