SolidJSS
SolidJSโ€ข3y agoโ€ข
7 replies
baptiste0928

How to avoid rerenders when using refetch ?

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
Was this page helpful?