question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Complex component first time loading

See original GitHub issue

I’m building a complex unicorn component for a page. The case is list of audios in a table as image below. Screenshot from 2021-07-22 05-42-01

Here my python code.

from django.core.paginator import Paginator
from django.utils.translation import ugettext_lazy as _  # noqa
from django_unicorn.components import UnicornView

from dashboard.models import Document


class AudioLibraryView(UnicornView):
    first_load = False
    items_per_page = 10
    title = ''
    page_index = 1
    paginator = None
    page = None

    class Meta:
        exclude = ()
        javascript_exclude = ('paginator', 'page', 'http_request', '_search_documents')

    # def hydrate(self):
    #     print('first_load', self.first_load)
    #     if self.first_load is True:
    #         self._search_documents()
    #     self.first_load = False

    def _search_documents(self):
        qs = Document.objects.get_documents_by_user(
            user=self.request.user
        )
        if self.title:
            qs = qs.filter(title__icontains=self.title)

        paginator = Paginator(qs, self.items_per_page)
        self.paginator = paginator
        self.page = paginator.page(self.page_index)
        return self.page

    def search_documents(self):
        self._search_documents()

    def next_page(self):
        self.page_index += 1
        self._search_documents()

    def previous_page(self):
        self.page_index = max(self.page_index - 1, 1)
        self._search_documents()

The problem that I found was that the function search_documents was called multiples times before the component render. That’s happened because I put a for loop calling search_documents and also the Pesquisa button to call search_documents. To solve this problem, I bind search_documents only on Pesquisa and the for loop iterates over page.object_list, that is loaded on _search_documents. However, I needed to put the fallowing code to load the table at first time load.

<script type="text/javascript">
  (function(){
    setTimeout(function(){document.getElementById('button-get-documents').click();}, 500);
  })();
</script>

My question is if there a native way to do this load at first time.

Here my unicorn html component code.


<div>     
          <div class="inline-flex flex-row max-w-sm md:max-w-md mb-6 items-center">

            <input unicorn:model="page_index" type="hidden" value="{{page_index}}">
            
            <div class="">
              <label class="">
                  <input unicorn:model.defer="title" type="text" name="name" class="border-radius-none mt-1 w-full rounded-md border-neutral-300 focus:border-primary-800" placeholder="{% trans "Title" %}" maxlength="100" required="" autocomplete="off">
              </label>
            </div>

            <div class="ml-4">
              <a id="btn-search-documents" unicorn:click="search_documents" class="flex cursor-pointer justify-between px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-primary-600 border border-transparent rounded-full active:bg-primary-600 hover:bg-primary-500 focus:outline-none focus:shadow-outline-primary">
                  <span class="jam jam-search mr-1 text-lg"></span>
                  <span>{% trans "Search" %}</span>
              </a>
            </div>
            
          </div>

          <div class="w-full overflow-hidden rounded-lg border-2 shadow-xs">
            <div class="w-full overflow-x-auto">
              <table class="w-full table-auto whitespace-no-wrap">
                <thead>
                  <tr class="text-xs font-semibold tracking-wide text-left text-gray-500 uppercase border-b dark:border-gray-700 bg-gray-50 dark:text-gray-400 dark:bg-gray-800">
                    <th class="px-4 py-3">{% trans "Title" %}</th>
                    <th class="px-4 py-3">{% trans "Voice" %}</th>
                    <th class="px-4 py-3">{% trans "Speed" %}</th>
                    <th class="px-4 py-3">{% trans "Created" %}</th>
                    <th class="px-4 py-3">{% trans "Status" %}</th>
                    <th class="px-4 py-3">{% trans "Pages" %}</th>
                    <th class="px-4 py-3">{% trans "Actions" %}</th>
                  </tr>
                </thead>
                <tbody class="bg-white divide-y dark:divide-gray-700 dark:bg-gray-800">
                  
                  {% for doc in page.object_list %}
                  
                  <tr class="dark:text-gray-400">
                    <td class="px-3 py-2">
                      <div class="flex items-center text-sm">
                        <div>
                          <a class="link text-primary-500" href="/html/soarvoice/soarvoice.html?text-editor&doc_id={{doc.id}}"><span class="font-semibold">{{doc.title}}</span></a>
                        </div>
                      </div>
                    </td>
                    <td class="px-3 py-2 text-sm">
                      {{doc.voice.name}}
                    </td>
                    <td class="px-3 py-2 text-sm">
                      {{doc.get_speed_display}}
                    </td>
                    <td class="px-3 py-2 text-sm">
                    {{doc.created|date:"d/m/Y"}}
                    </td>
                    <td class="px-3 py-2 text-sm">
                        {% if doc.status %}
                            <span class="px-2 py-1 font-semibold leading-tight text-primary-700 bg-primary-100 rounded-full dark:bg-primary-700 dark:text-primary-100">{% trans "Done" %}</span>
                        {% else %}
                            <span class="inline px-2 py-1 font-semibold leading-tight text-orange-700 bg-orange-100 rounded-full dark:bg-orange-700 dark:text-primary-100">{% trans "Working" %}
                            </span>
                        {% endif %}
                    </td>
                    <td class="px-3 py-2 text-sm">
                    {{doc.created|date:"d/m/Y"}}
                    </td>
                    <td class="px-3 py-2 text-sm">
                      <div class="inline-flex">
                        <button unicorn:click="delete({{doc.id}})" class="mr-2 flex px-3 py-1 text-xs font-bold leading-5 text-white transition-colors duration-150 bg-primary-600 border border-transparent rounded-md active:bg-primary-600 hover:bg-primary-700 focus:outline-none focus:shadow-outline-primary">
                          <span class="text-xl jam jam-play"></span>
                          {% trans "Play" %}
                        </button>
                        <button unicorn:click="delete({{doc.id}})" class="px-3 py-1 text-xs font-bold leading-5 text-white transition-colors duration-150 bg-red-600 border border-transparent rounded-md active:bg-red-600 hover:bg-red-700 focus:outline-none focus:shadow-outline-red">
                          {% trans "Delete" %}
                        </button>
                      </div>
                    </td>
                  </tr>
                  
                  {% endfor %}

                </tbody>
              </table>
            </div>
            <div class="grid px-4 py-3 text-xs font-semibold tracking-wide text-gray-500 uppercase border-t dark:border-gray-700 bg-gray-50 sm:grid-cols-9 dark:text-gray-400 dark:bg-gray-800">
              <span class="flex items-center col-span-3">
                {{ page_index }} {% trans "of" %} {{paginator.num_pages}}
              </span>
              <span class="col-span-2"></span>
              <!-- Pagination -->
              <span class="flex col-span-4 mt-2 sm:mt-auto sm:justify-end">
                <nav aria-label="Table navigation">
                  <ul class="inline-flex items-center">
                    <li>
                      <button unicorn:click="previous_page" class="flex align-middle px-3 py-1 rounded-md rounded-l-lg focus:outline-none focus:shadow-outline-purple" aria-label="Previous">
                        <svg aria-hidden="true" class="w-5 h-5 fill-current" viewBox="0 0 20 20">
                          <path d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" fill-rule="evenodd"></path>
                        </svg>
                        <span class="inline text-md">{% trans "Previous" %}</span>
                      </button>
                    </li>
                    <li>
                      <button unicorn:click="next_page" class="flex align-middle px-3 py-1 rounded-md rounded-r-lg focus:outline-none focus:shadow-outline-purple" aria-label="Next">
                        <span class="inline text-md">{% trans "Next" %}</span>
                        <svg class="w-5 h-5 fill-current" aria-hidden="true" viewBox="0 0 20 20">
                          <path d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" fill-rule="evenodd"></path>
                        </svg>
                      </button>
                    </li>
                  </ul>
                </nav>
              </span>
            </div>
          </div>
</div>

<script type="text/javascript">
  (function(){
    setTimeout(function(){document.getElementById('btn-search-documents').click();}, 500);
  })();
</script>

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:11 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
nielsonsantanacommented, Aug 7, 2021

@adamghill, I think you can close this issue since there no problem on django-unicorn. Thanks.

0reactions
adamghillcommented, Jul 25, 2021

Interesting! Yes, I use pickle to cache some parts of the component and it can’t pickle HttpRequest (I end up dealing with requests in my code to make them cacheable). I’ll see if maybe there is a better error message I could surface to make it more obvious that things might break.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Load Data Easily With React Hooks - Medium
First things first, let's build out a new functional component that we'll ... load data each time a prop changes or only on...
Read more >
Lazy loading React components - LogRocket Blog
The concept of lazy loading is simple: initialize objects that are critical to the user interface first and quietly render noncritical items ...
Read more >
React useEffect to have different behavior on first load and ...
When you call useEffect() you can return a clean-up function. That cleanup function gets called when the component is unmounted.
Read more >
Run useEffect Only Once - CSS-Tricks
Run useEffect Only Once ... React has a built-in hook called useEffect. Hooks are used in function components. The Class component comparison to ......
Read more >
How We Reduced Our React App's Load Time by 60% - InfoQ
The first step to optimising is measuring. Only once we identified the bottlenecks could we eliminate them. Chrome DevTools offers powerful ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found