This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-06
Channels
- # aleph (15)
- # beginners (40)
- # boot (14)
- # cider (90)
- # cljs-dev (132)
- # cljsrn (25)
- # clojars (7)
- # clojure (188)
- # clojure-chicago (4)
- # clojure-dusseldorf (1)
- # clojure-greece (9)
- # clojure-italy (43)
- # clojure-russia (16)
- # clojure-sg (7)
- # clojure-spec (39)
- # clojure-uk (81)
- # clojurescript (170)
- # component (5)
- # core-async (7)
- # cursive (49)
- # data-science (65)
- # datascript (3)
- # datomic (27)
- # graphql (3)
- # hoplon (4)
- # instaparse (56)
- # klipse (129)
- # leiningen (1)
- # lumo (28)
- # off-topic (4)
- # om (15)
- # onyx (54)
- # overtone (7)
- # pedestal (7)
- # re-frame (9)
- # reagent (72)
- # ring (33)
- # ring-swagger (2)
- # spacemacs (1)
- # untangled (19)
- # vim (2)
- # yada (12)
I figured it out. Think I'll add an updated example to the reagent cookbook.
Have a problem with component update, when atom state changed, have some child in component-will-update, but when atom changed i receive TypeError: Cannot read property 'set' of undefined
and similar...
That's not enough information to guess the cause
Can you post your code?
Component re-render successful when atom changed, but it didn't apply property for new :dataSource.
still not enough context to see the issue I'm afraid
check this as an example for including foreign js in a reagent component: https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/google-maps
oh, also think about when component-will-update fires
that's only if props change, or component state changes, or the ratom triggers a force update
what I'd do is build an inner component that takes the data as a prop
then have an outer component
(defn outer [] [inner @state])
in the lifecycle methods you'll have access to the new state in the props
check this for how to access props: https://www.martinklepsch.org/posts/props-children-and-component-lifecycle-in-reagent.html
that gives you a clean separation of the reagent-controlled outer component (which derefs the ratom), and the stateful, sideffectful inner component
hi folks, I need some help with figuring out how to mimic this snippet in hiccup/reagent
https://github.com/captivationsoftware/react-sticky/blob/master/examples/basic/basic.js#L26-L33
I’ve lost track of all the incantations I’ve tried
# Step 1 Add the following to project.clj
[cljsjs/react-sticky "5.0.8-0"]
# Step 2
Require react-sticky in your ns
(ns foo.core
(:require
[cljsjs.react-sticky]))
# Step 3
Create reagent versions of the sticky components
(def sticky-container (reagent/adapt-react-class (aget js/ReactSticky "StickyContainer")))
(def sticky (reagent/adapt-react-class (aget js/ReactSticky "Sticky")))
# Step 4
Use reagent components as you'd expect
[sticky-container
[sticky ... ]]
yeah, but the syntax changed in 6.0.1 and I’m trying to get it working before sending a cljsjs PR for the update
I’m using 5.0.8 atm, wanna bump to 6.0.1 to see if these annoying prop-type warnings go away 🙂
As I minor note, I'd replace aget
with just property access: (reagent/adapt-react-class js/ReactSticky.StickyContainer)
, aget
is meant just for arrays
@kennethkalmer ah sorry, i missed the intent of your question 😁
no sweat, awesome reply still!
that would definitely help others, so never stop doing that 😄
I just can’t figure out this piece:
<Sticky>
{
({ isSticky, wasSticky, style, distanceFromTop, distanceFromBottom, calculatedHeight }) => {
console.log({ isSticky, wasSticky, style, distanceFromTop, distanceFromBottom, calculatedHeight });
return <Header style={style} />
}
}
</Sticky>
Hmm, lambda function using JS object destructuring maybe?
But what is calling the function in JSX
I either get react-sticky complaining that the child is not a function, or react blowing up with an undefined somewhere
Oh, the Sticky children must be a function... not sure if that works with Reagent
Sticky expects it's React children to be a function. The function takes a single map argument with the keys isSticky
, wasSticky
, etc.
I'd assume you could do [my-component {:props ,,,} (fn [] ,,,)]
? ...does that not work?
tried it, didn’t work
the parameter is not a map, but JS object
same exception: Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in. Check the render method of Sticky
.
Does the exception say if it is from Reagent or React?
react-dom.inc.js:17896 Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of `Sticky`.
at invariant (react-dom.inc.js:17896)
at instantiateReactComponent (react-dom.inc.js:16037)
at instantiateChild (react-dom.inc.js:4267)
at react-dom.inc.js:4294
at traverseAllChildrenImpl (react-dom.inc.js:16549)
at traverseAllChildrenImpl (react-dom.inc.js:16565)
at traverseAllChildren (react-dom.inc.js:16644)
at Object.instantiateChildren (react-dom.inc.js:4293)
at ReactDOMComponent._reconcilerInstantiateChildren (react-dom.inc.js:10378)
at ReactDOMComponent.mountChildren (react-dom.inc.js:10417)
apologies, should have pasted the whole thing
it is the same wether :children (fn [] ...)
or as the only child in the hiccup vector
React JSX format probably does some magic for the functions
is it worth opening an issue on reagent if this isn’t supported?
Obviously passing functions as parameters to native Cljs components works fine
i’m considering dropping the component, but I fear others might go down this rabbit hole too… since it is on cljsjs, and I’ve done the work to issue a PR for 6.0.1
Did you add console.log
or such to the function, what if the function is called okay but the return value doesn't work?
return <Header style={style} />
in the example would be compiled to proper React call, but if you just return [Header]
in Reagent it is just a cljs vector
just added a log, it got called
Try wrapping the return value to reagent.core/as-element
OMG, used as-component
and it worked, testing as-element
they are the same, as-component
is just deprecated name
Hah, that took some thinking to understand
magic, I’m still not sure I understand it (yet)
but I’ll let it simmer and update the cljsjs/react-sticky readme with a proper example
The JSX return <Header style={style} />
is compiled to React.createElement
call so the function returns proper React element
Doesn't happen automatically with Reagent
aha, makes sense
this also makes sense why as-element
on its own didn’t work, and instead needed to be wrapped now with (fn [props] (reagent.core/as-element [:hiccup]))
thanks so much for your help on figuring this out! hopefully with this stuff in the readme we can put it to bed for a bit
Google showed I wasn’t the first person in here asking for help with react-sticky
I’m knackered, thanks again everyone for chiming in, learned a lot 😴
also glad to have learned something new. And the function-as-children pattern isn't too uncommon in React-land, so this'll be useful as I learn more about Reagent
This pattern might be useful even for Cljs components
Like parameterizing autocomplete component items or such
Though in that case the functions might be in props, but maybe there is some benefit in returning Element from the functions
in React, it's often used to pass state/callbacks down to children to decouple stuff, whereas it seems like most CLJS projects don't keep a lot of local state in general
It depends, in applications no, but when writing low-level reusable components local state is often necessary or at least very helpful
But there are other ways to handle local state in those components also