You need to decouple a little bit… first set loading status, then run the query.
def handle_event("search", %{"q" => q}, socket) do
send(self, {:run_search, q})
{:noreply, assign(socket, :set_loading, true)}
end
def handle_info({:run_search, q}, socket) do
# do the actual work
socket
|> assign(:set_loading, false)
|> assign(:result, ...)
{:noreply, socket}
end