Fork me on GitHub
#helix
<
2022-09-12
>
Wes Richardet16:09:06

Am I correct in reading that live-reload is an experimental feature at the moment?

lilactown18:09:07

that's right

lilactown18:09:28

it mostly works, but loses state in some places it might not necessarily need to, and is hard to configure at the moment

Joe Dumont23:09:46

Hi! I've been working through the React Docs with Helix, and am circling back to a key warning I got implementing the ProductTable component in this section: https://beta.reactjs.org/learn/thinking-in-react (also pasted at bottom). In Helix I wrote it like this:

(defnc product-table
  [{:keys [products filter-text in-stock-only]}]
  (let [products (if in-stock-only (filter #(:stocked %) products) products)
        products (filter #(not= -1 (.indexOf (.toLowerCase (:name %)) (.toLowerCase filter-text))) products)
        groups (group-by :category products)]
    (d/table
     (d/thead
      (d/tr
       (d/th "Name")
       (d/th "Price")))
     (d/tbody
      (for [[group data] groups]
        (<>
         ($ product-category-row {:category group :key group})
         (for [row data]
           ($ product-row {:data row :key (:name row)}))))))))
This has the correct functionality as far I can tell, but I get a warning that "Each child in a list should have a unique 'key' prop" on the render of product-table. These are the same key props used in the tutorial, and are all unique. I'm wondering if it's the nested list comprehension causing the key issue. Thanks for any insights or suggestions. The original for completeness:
function ProductTable({ products, filterText, inStockOnly }) {
  const rows = [];
  let lastCategory = null;

  products.forEach((product) => {
    if (
      product.name.toLowerCase().indexOf(
        filterText.toLowerCase()
      ) === -1
    ) {
      return;
    }
    if (inStockOnly && !product.stocked) {
      return;
    }
    if (product.category !== lastCategory) {
      rows.push(
        <ProductCategoryRow
          category={product.category}
          key={product.category} />
      );
    }
    rows.push(
      <ProductRow
        product={product}
        key={product.name} />
    );
    lastCategory = product.category;
  });

  return (
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Price</th>
        </tr>
      </thead>
      <tbody>{rows}</tbody>
    </table>
  );
}

lilactown03:09:09

your code is slightly different than the tutorial. in the tutorial. there is a single rows array of elements. in your version, there are multiple collections: one lazy sequence of elements which is generated by iterating over each category, and then each of those elements contains another lazy sequence of elements with the actual product-row the warning you're getting is because there is no :key prop on the element <> returned by the outer lazy sequence

lilactown03:09:45

ah I see that you even added the :key to the product-row-category. it should be on the <> element, actually

🙌 1
lilactown03:09:35

if you wanted, you could also change your example to be more similar to the tutorial by using mapcat

lilactown03:09:24

(d/tbody
      (mapcat
       (fn [[group data]]
         (cons
          ($ product-category-row {:category group :key group})
          (for [row data]
            ($ product-row {:data row :key (:name row)}))))
       groups))

🙌 1
Joe Dumont03:09:15

Ah ha, thank you! I like that mapcat version. I didn't realize the key could/should go on <> {:key group}

lilactown16:09:20

also, a minor request: would you be willing to publish your code when you're done with the tutorial? I have a few people I'm mentoring that have wanted to go through the same exercise (doing the react tutorial in helix) and it would be great to have an example of someone who already did it. no pressure, though!

Joe Dumont23:09:32

@U4YGF4NGM Absolutely! I was going to offer to pull out/clean up a couple of examples for the docs if welcome. I've been keeping code here: https://github.com/iwrotesomecode/react-docs-helix I haven't replicated everything from the tutorial, but tried to hit all the main features. I've been using promesa delays to simulate api calls, but there perhaps a more standard approach folks prefer. This roughly covers most topics/hooks from the beta docs, though I haven't gone through the final couple of subsections in the "Escape Hatches" section yet (more examples of custom hooks, and useSyncExternalStore )

1
lilactown16:09:39

this is so cool! thanks for making it public. I'm going to show it off to people at work 🙂