Hi, I'm trying to build a simple todo list app using Solid. Everything has been fine so far, I really enjoy using Solid!
When I decided to add CSS transitions when adding an item to the todo list, I noticed that all items in the list were re-rendered each time they were added. After some investigation, I found that this re-rendering was caused by refetch, which when called causes a re-rendering of the entire list. Using mutate works as expected, so I suspect that the reactivity is lost because the list is replaced with a whole new object.
What's the best way to avoid this kind of re-renders?
// api.ts
const [todos, { mutate, refetch }] = createResource(fetchTodos)
async function fetchTodos(): Promise<Todo[]> {
const api = useApi()
return await api<Todo[]>('/user/todos')
}
export async function createTodo(
todo: { title: string; description: string; dueTime: Date },
): Promise<Todo> {
// ... (constructing request)
const createdTodo = await api<Todo>(
'/todos',
{ method: 'POST', body: requestBody },
)
mutate(todos => [...todos ?? [], createdTodo])
refetch() // <- this call causes the re-render
return createdTodo
}
export { todos as userTodos }
// TodoList.tsx
// ...
const TodoListPart: Component<{ name: string; status: TodoStatus }> = (props) => {
const filteredTodos = () => userTodos()?.filter(todo => todo.status === props.status) ?? []
return (
<div class="mt-8">
<h2 class="text-lg font-bold">{props.name}</h2>
<For each={filteredTodos()} fallback={<EmptyPart />}>
{todo => <TodoItem title={todo.title} status={todo.status} />}
</For>
</div>
)
}
const TodosList: Component = () => {
return (
<Suspense fallback={<Loading />}>
<TodoListPart name="Not started" status={TodoStatus.NOT_STARTED} />
<TodoListPart name="Todo" status={TodoStatus.TODO} />
<TodoListPart name="In progress" status={TodoStatus.IN_PROGRESS} />
<TodoListPart name="Done" status={TodoStatus.DONE} />
</Suspense>
)
}
export default TodosList