Fork me on GitHub
#reagent
<
2021-12-09
>
mathias_dw14:12:17

Hi, I'm getting the "every element in a seq should have a unique key" warning, but I dont understand why:

[:tbody
         (->> @sorted-docs
              (mapcat
               (fn [doc]
                 (into [[docs-table-row doc]]
                       (map #(vector search-result-row %)
                            (::ss/full-text-search-results doc)))))
              (map-indexed (fn [idx el] ^{:key idx} el)))]

juhoteperi14:12:26

^{:key idx} metadata is added to the el SYMBOL here, not the vector defining the element here. You could use (with-meta el {:key idx}) here. Or [^{:key idx} [docs-table-row doc]] would attach the metadata to the vector which works, but then you'd need the idx inside the mapcat.

👍 1
juhoteperi14:12:17

And OK, the mapcat fn anyways adds more elements from the map part.

juhoteperi14:12:35

You could consider using fragments here, to avoid mapcat:

[:tbody
 (for [doc @sorted-docs]
  [:<>
   {:key (:id doc)} ;; if doc has some kind of ID
   [docs-table-row doc]
   (for [result (::ss/full-text-search-results doc)]
     ^{:key ...} [search-result-row result])])]

juhoteperi14:12:16

The resulting DOM tree is the same, but you avoid the need to flatten the datastructures when rendering the elements.

👍 1
mathias_dw14:12:30

thanks a lot! It all makes sense now 🙂

mathias_dw14:12:53

doesnt the (map-indexed) part add the key to the vectors correctly?

mathias_dw14:12:43

(search-result-row and docs-table-row are both functions returning a [tr with stuff in it

mathias_dw14:12:18

ok, making it

(into [:tbody] (->> ...
seems to solve it. Just dont understand why...

juhoteperi14:12:26

^{:key idx} metadata is added to the el SYMBOL here, not the vector defining the element here. You could use (with-meta el {:key idx}) here. Or [^{:key idx} [docs-table-row doc]] would attach the metadata to the vector which works, but then you'd need the idx inside the mapcat.

👍 1
juhoteperi14:12:35

You could consider using fragments here, to avoid mapcat:

[:tbody
 (for [doc @sorted-docs]
  [:<>
   {:key (:id doc)} ;; if doc has some kind of ID
   [docs-table-row doc]
   (for [result (::ss/full-text-search-results doc)]
     ^{:key ...} [search-result-row result])])]

Wilson Velez18:12:03

hi, I’m trying to “translate” this code to clojure (https://uppy.io/docs/react/initializing/#Functional-Components), the useUppy is a react hook, and I don’t know how to use it

import Uppy from '@uppy/core'
import React from 'react'
import { DashboardModal, useUppy } from '@uppy/react'

function MyComponent () {
  const uppy = useUppy(() => {
    return new Uppy()
      .use({ autoProceed: true' })
  })

  return <DashboardModal uppy={uppy} />
}
This is my try
(ns online-app.download
  (:require ["@uppy/core" :as Uppy]
            ["@uppy/react" :refer [FileInput useUppy]]))
(defn page
  []
  (let [uppy-instance (useUppy (.use (Uppy.) {:autoProceed true
                                              :restrictions {:minNumberOfFiles nil
                                                             :maxNumberOfFiles 1
                                                             :maxFileSize      "10mb"
                                                             :allowedFileTypes "pdf"}}))]
    [:div "updaload"
     [:f> FileInput {:uppy uppy-instance
                     :pretty true
                     :inputName "files[]"}]]))
But when I load the page I’m getting Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM)........ any tips? thanks

Wilson Velez19:12:37

at the beginning I thought I was following the same pattern from the code in that page but I was wrong, I modified the exact example to my needs and the hook is no longer an error

(defn example []
  (let [[count set-count] (react/useState 0)]
    [:div
     [:p "You clicked " count " times"]
     [:button
      {:on-click #(set-count inc)}
      "Click"]])))

(defn root []
  [:div
   [:f> example]])

Wilson Velez19:12:12

(defn example []
  (let [uppy-ins (useUppy #(.use (Uppy.) {:autoProceed  true
                                      :restrictions {:minNumberOfFiles nil
                                                     :maxNumberOfFiles 1
                                                     :maxFileSize      "10mb"
                                                     :allowedFileTypes "pdf"}}))]
    [:> FileInput {:uppy uppy-ins
                     :pretty true
                     :inputName "files[]"}]))

Wilson Velez19:12:19

@U4YGF4NGM thanks, now my problem is something related with uppy no receiving the thing it needs Uppy.js:1047 Uncaught TypeError: Expected a plugin class, but got object. Please verify that the plugin was imported and spelled correctly. at Uppy.use

Wilson Velez19:12:45

@kah0ona I will spend some time trying to work with the react version of uppy now that I’m moving on, if I don’t have luck I will give the js version a try

kah0ona19:12:43

see usage example at bottom of that gist

kah0ona19:12:12

I compile those external modules using webpack, package.json: { “name”: “….“, “version”: “0.0.1", “scripts”: { “watch”: “webpack -d --watch”, “build”: “webpack -p --devtool source-map” }, “dependencies”: { “@cljs-oss/module-deps”: “^1.1.1", “uppy”: “^1.29.1" }, “devDependencies”: { “webpack-cli”: “^2.1.5” } }

kah0ona19:12:56

although tbh, I still am kind of intimidated by those esoteric (from my pov) JS tools 😉

kah0ona19:12:34

but, it’s nice that it’s possible!

Wilson Velez19:12:08

@kah0ona you are using the javacript library instead of the react components, right?

kah0ona19:12:04

I think this was the first thing I got working

kah0ona19:12:13

but it’s been a while; two years ago or so.

kah0ona19:12:40

so not really sure why I did what I did (and I am by no means an expert when it comes to that topic :-))

Wilson Velez19:12:28

thanks, I really appreciate your help, there some parts in your gist, that I didn’t know how to use it

kah0ona19:12:59

I think the most idiomatic way nowadays would be the react components though? But since the JS interop is quite small in my case, only a few lines, it works fine for my case

olaf22:12:20

Hi, I've a function that has a hook and should render some children

(defn content-wrapper [& children]
  (let [theme (obj->clj (useTheme))]
    [:div {:class (<class content-st theme)}
     children]))

(defn content [& children]
  [:f> content-wrapper children])
How can I avoid the Every element in a seq should have a unique :key ? Is use it like this
(defn app []
  [content
    [:div ...]
    [:div ...]
  ])

p-himik01:12:31

It's documented in Reagent repo. (into [:div ...] children)

✅ 1