News for hackers. Stuff that matters.
Re:How to write PureScript react components to replace JavaS... by chvid on Thursday June 25, 2020 @01:30AM (#23637234)
This is the corresponding code written in React using hooks:

    export const Counter = ({label, counterType, onClick}) => {
        const [counter, setCounter] = useState(0);
        return (
            <button onClick={() => {
                counterType == "Increment" && setCounter(counter + 1);
                counterType == "Decrement" && setCounter(counter - 1);
                onClick && onClick();
            }}>
                {label}: {counter}
            </button>
        );
    }
I think the case for PureScript React would be more convincing if the code you ended up with was loosely as concise as the above.
Re:How to write PureScript react components to replace JavaS... by diggan on Thursday June 25, 2020 @05:15AM (#23638545)
Did someone say concise? Here is a ClojureScript + Reagent example for whoever is interested in that:

  (defn Counter [{:keys [label counterType onClick]
                  :or {onClick (fn [])}}]
    (let [count (r/atom 0)]
      [:button
        {:onClick #(do (swap! count (condp = counterType
                                      :increment inc
                                      :decrement dec))
                       (onClick))}
        (str label ": " @count)])))
Re:How to write PureScript react components to replace JavaS... by edjroot on Thursday June 25, 2020 @06:06AM (#23638861)
Awesome! Would you mind talking some more about your experience with it? I just got started with Clojure and Fulcro[1] (a full-stack framework) and I'm really, really excited about the possibilities. Have you heard about it?

Here are some features off the top of my head (at least that's what they claim):

- Well-integrated stack, so very little friction

- “Datomic on the front end”: Client-side time-traveling database with automatic normalization, querying via EQL (kinda like GraphQL but more idiomatic and supposedly more powerful), “co-locating” queries in the UI.

- React bindings and a Semantic UI library

- Lets you swap anything you “outgrow”

- Lots of learning material (but still lacking in some areas from a cursory look). The author seems to be very active on Slack (Clojurians #fulcro).

- Fulcro RAD[2] (currently alpha) looks like it's going to reduce friction even further.

There's probably more cool stuff I don't remember now.

The two things I'm still insecure about with Clojure are its dynamically typed nature (but I'd be glad to hear about how that isn't a problem) and that the ecosystem doesn't seem to hold your hand too much (again, I'd like to hear another point of view).

[1] https://fulcro.fulcrologic.com/benefits.html

[2] https://github.com/fulcrologic/fulcro-rad

Re:How to write PureScript react components to replace JavaS... by slifin on Thursday June 25, 2020 @06:34AM (#23639038)
I'm making this same journey (I'm on video 5), and I'm making some notes for each video in Roam and teaching/learning each video every week via Google Meet on Bristol's Clojure Meetup

I recommend using clj-kondo to catch the kinds of silly mistakes a type system is usually good for, yesterday we discovered that the react component interop is really good, we decided to try using https://chakra-ui.com/ over semantic ui and it's really straight forward to use React components that have no awareness of Fulcro or CLJS

I think in terms of hand holding Fulcro does a really good job once you get into the weeds because it has an opinion and documentation for many problems, if you want to join us we're #bristol-clojurians on slack

Re:How to write PureScript react components to replace JavaS... by monsieurbanana on Thursday June 25, 2020 @09:06AM (#23640241)
Oh hey! I've been to Bristol's Clojure Meetup last year! Or was it two years ago? Anyways, happy to hear about it. I'm not in the UK anymore, but I'll drop by next time I visit.
Re:How to write PureScript react components to replace JavaS... by myth_drannon on Thursday June 25, 2020 @11:53AM (#23642061)
>I'm making this same journey (I'm on video 5) >

Sorry, which videos are you watching?

Re:How to write PureScript react components to replace JavaS... by CraigJPerry on Thursday June 25, 2020 @09:27AM (#23640460)
There's something attractive about this example but i'm struggling to figure out why i think that. What is it that makes this attractive?

  + There's a signal to noise ratio that's off the charts
  + You've not cheated to achieve succinctness; there's no blackbox.nowDrawTheRestOfTheOwl()

  - I don't think that's "pretty" code
  - i don't find it easy to parse, i had to read your example with my index finger pressed against the screen as i traced through it - i didn't have to do that with the Typescript further example down-thread
Re:How to write PureScript react components to replace JavaS... by filoeleven on Thursday June 25, 2020 @01:33PM (#23643194)
Just curious: what’s your level of fluency with Clojure/lisp syntax vs C-style syntax?

I found that learning to read the lisp-style indentation (which is purely by convention but has widespread acceptance and tooling support) was a pretty fast process with a solid payoff. It becomes easier to jump between levels of detail, and I now find it to be more readable than C-style syntax, even though I only write JS for work.

For example, in the code above, “what it does“ is made clear by reading downward without looking very far to the right: it draws a button with a click handler and a label. There is a guarantee offered by immutability that says “anything deeper than my current level cannot affect things outside of itself.”

That may sound like a lie, since the :onClick handler updates an atom, but knowing that a dereferenced atom (@count) has a stable value during the lifetime of the function call resolves it.

I don’t know how strong that guarantee is with other lisps; I think Clojure’s immutability plays a key role though.

Re:How to write PureScript react components to replace JavaS... by CraigJPerry on Thursday June 25, 2020 @04:20PM (#23645199)
Yeah i agree the readability is purely a lack of familiarity on my part rather than some fundamental difficulty in the syntax.

If anything, the clojure syntax has fewer rules to understand - from my very limited knowledge of it.

Re:How to write PureScript react components to replace JavaS... by oweqruiowe on Thursday June 25, 2020 @09:37AM (#23640567)
I use Clojurescript professionally and it has the best state management story with re-frame over JS and any transpile-to-js language. It's so lovely.
Re:How to write PureScript react components to replace JavaS... by oweqruiowe on Thursday June 25, 2020 @02:34PM (#23643942)
To expand, I love this document even from the standpoint of how to structure client-side code http://day8.github.io/re-frame/application-state

It applies to React/Redux folks as well.

> There are benefits to having data in the one place:

> Here's the big one: because there is a single source of truth, we write no code to synchronise state between many different stateful components. I cannot stress enough how significant this is. You end up writing less code and an entire class of bugs is eliminated. (This mindset is very different to OO which involves distributing state across objects, and then ensuring that state is synchronised, all the while trying to hide it, which is, when you think about it, quite crazy ... and I did it for years).

> Because all app state is coalesced into one atom, it can be updated with a single reset!, which acts like a transactional commit. There is an instant in which the app goes from one state to the next, never a series of incremental steps which can leave the app in a temporarily inconsistent, intermediate state. Again, this simplicity causes a certain class of bugs or design problems to evaporate.

Re:How to write PureScript react components to replace JavaS... by noelwelsh on Thursday June 25, 2020 @05:13AM (#23638528)
FWIW here's a Purescript example from the `purescript-react-basic-hooks` homepage[1]. It's not 100% identical but it is fairly close.

  mkCounter :: Effect (ReactComponent {})
  mkCounter = do
    component "Counter" \props -> React.do
      counter /\ setCounter <- useState 0

      pure
        $ R.button
          { onClick: handler_ do
              setCounter (_ + 1)
          , children:
              [ R.text $ "Increment: " <> show counter ]
          }
Your aesthetic / background may differ from mine, but I find the Purescript version easier to read.

[1]: https://github.com/spicydonuts/purescript-react-basic-hooks

Re:How to write PureScript react components to replace JavaS... by diggan on Thursday June 25, 2020 @07:15AM (#23639287)
Not sure I misunderstand the code that you're posting, but seems to not have the whole increment vs decrements parts in it, which would be interesting to see.
Re:How to write PureScript react components to replace JavaS... by lalaithion on Thursday June 25, 2020 @01:19PM (#23643005)
This is a closer comparison.

    mkCounter :: String -> (Int -> Int) -> Effect (ReactComponent {})
    mkCounter label op = do
      component "Counter" \props -> React.do
        counter /\ setCounter <- useState 0

        pure
          $ R.button
            { onClick: handler_ do
                setCounter op
            , children:
                [ R.text $ label <> ": " <> show counter ]
            }
now you can call

    mkCounter "Increment" (_ + 1)
Re:How to write PureScript react components to replace JavaS... by noelwelsh on Thursday June 25, 2020 @10:51AM (#23641416)
You are correct, which is why I said "[I]t's not 100% identical".

Although I can read Purescript reasonably well I'm not so proficient writing it (I do most of my programming in a different FP language, so I understand the concepts but not the specifics.) I didn't attempt to modify the code I pulled from the example because it would take more time than I have to install Purescript and check my modifications.

It would be simple to add this functionality. This equivalent of the `counterType` would be an algebraic data type, defined looking something like

  data counterType = Increment | Decrement
and usage something like

  case counterType of
    Increment -> ... make increment here ...
    Decrement -> ... make decrement here ...
Re:How to write PureScript react components to replace JavaS... by TexInWien on Thursday June 25, 2020 @10:33AM (#23641184)
The following line defines a function (the syntax is known as an 'operator section'):

  (_ + 1)
Equivalent to this JS function:

  x => x + 1
Operator Sections: https://github.com/purescript/documentation/blob/master/lang...
Re:How to write PureScript react components to replace JavaS... by rkangel on Thursday June 25, 2020 @10:40AM (#23641268)
I think the parent's point is that it only includes increment and not decrement.
Re:How to write PureScript react components to replace JavaS... by crooked-v on Thursday June 25, 2020 @03:22AM (#23637776)
Also, you can get compile-time strict typing in Typescript with some minor annotations added to that:

    export const Counter: FunctionComponent<{
        label: string;
        counterType: 'Increment' | 'Decrement';
        onClick: () => void
    }> = ({ label, counterType, onClick }) => {
        const [counter, setCounter] = useState<number>(0);
        return (
            <button onClick={() => {
                counterType == "Increment" && setCounter(counter + 1);
                counterType == "Decrement" && setCounter(counter - 1);
                onClick && onClick();
            }}>
                {label}: {counter}
            </button>
        );
    }
Re:How to write PureScript react components to replace JavaS... by chvid on Thursday June 25, 2020 @03:30AM (#23637837)
Yes.

You can add types if you want. And maybe one can discuss if there is a more elegant syntax than the C-style syntax of JavaScript (there is ...).

Other than that. I think the code is about as concise as it gets.

Re:How to write PureScript react components to replace JavaS... by ddek on Friday June 26, 2020 @04:32AM (#23649911)
There is a change I’d make though - I’d memo-ise the click handler with useCallback. By using the function ‘overload’ on setState, which is guaranteed not to change, the callback will only be calculated (?) when the onclick handler changes. The setState would look like this: setState(c => c + 1);. Right now, the callback is interpreted on every render cycle.
Re:How to write PureScript react components to replace JavaS... by kalyantm on Thursday June 25, 2020 @01:48AM (#23637300)
Exactly my thought. I've always loved FP, I write JS in a FP style at work, and have always wanted to get into learning something like Elm/PureScript (and eventually Haskell) but I feel like it takes ages to get productive. That PureScript React example alone has me thinking twice. But as a general question, what would be a better way to approach these languages?
Re:How to write PureScript react components to replace JavaS... by k_bx on Thursday June 25, 2020 @03:38AM (#23637881)
Elm shouldn't take more than a week to be productive if you know other existing language. I ran a study group where people spent few hours a week, the group took 7 meetings to finishing the book and discussing a variety of possible problems to solve with Elm. It's a much simpler language than PureScript.
Re:How to write PureScript react components to replace JavaS... by bgorman on Thursday June 25, 2020 @02:09AM (#23637398)
Consider looking at ReasonML and ReasonReact, you can write stringly typed code at first, later you can start relying on type inference and ADTs
Re:How to write PureScript react components to replace JavaS... by omniscient_oce on Thursday June 25, 2020 @03:47AM (#23637936)
Yeah, ReasonML and ReasonReact are great because you're still writing JSX and not some over-engineered voodoo rewrite of React and/or JS but you get the power of strong types and ADTs and a super fast compiler.
Re:How to write PureScript react components to replace JavaS... by hombre_fatal on Thursday June 25, 2020 @11:34AM (#23641861)
I think FP UI solutions don't necessarily win the 10-liner demo (except for representing client state with an AGDT), but your app also isn't a 10-liner.

FP approaches to UI like Elm win the 100+ line comparisons for reasons you can't see, like minimizing runtime errors and making it so that impossible states are impossible at the type level.

Unfortunately it's hard to see the benefits until you get your hands dirty.

I use Elm in production on some apps and its a good place to start if you want simplicity. Personally, Purescript never interested me because I don't like all the complexity of more advanced Haskell features. While Elm specifically avoids certain advanced features to stay simple. You might like it given your concerns.

Re:How to write PureScript react components to replace JavaS... by rhlsthrm on Thursday June 25, 2020 @06:45AM (#23639103)
Can you explain more about writing JS in an FP style? I'd love to start to incorporate more FP in my JS but I don't really know how to start doing that. I've looked at fp-ts but it seems like that would require a full rewrite. Any tips for how to basically start from 0 and start to implement FP into an existing JS/TS codebase?
Re:How to write PureScript react components to replace JavaS... by pocket_titan on Thursday June 25, 2020 @08:08AM (#23639687)
I'd suggest just learning and applying fp principles in JS incrementally. You'll feel a bit constrained at first (in part b/c JS allows you to do many "dirty" things), but you'll end up writing better code. Try to rely on 1) pure functions/no side-effects: a functions return value should be completely determined by its input 2) immutability: no Array.push, pop, or any method that modifies its input values 3) recursion instead of for & while loops.

You'll probably feel the need for stronger typing at some point when adhering to these principles, and that's when I'd suggest looking at Typescript. By trying the things above you'll likely get familiar with the issues TS is trying to solve & you'll appreciate it more. Note that fp-ts is just a "helper" library for functional concepts, but it won't teach you their value or how to use them.

Also: many libraries have fp variations! Next time you reach for lodash, try lodash/fp instead: it has the same tools you'll already be familiar with, but implemented in a functional manner.

Re:How to write PureScript react components to replace JavaS... by quickthrower2 on Thursday June 25, 2020 @03:22AM (#23637783)
That is why I like Typescript as an option. Protect me from my dumb mistakes with types, but let me be fast and loose like JS.
Re:How to write PureScript react components to replace JavaS... by jrh206 on Thursday June 25, 2020 @05:32AM (#23638658)
Posting code on the internet - dangerous business!

I think the counter updates should use functional updates, since they depend on the current state. My understanding is that this can lead to a potential race condition, although I'm not 100% on the details.

  setCounter(currentCounter => currentCounter + 1)
https://reactjs.org/docs/hooks-reference.html#functional-upd...

Interestingly your code is similar to some the first code in the basic 'into to hooks' section of the docs. Perhaps it's not a huge issue? Maybe somebody else who knows a bit more about React internals can chime in.

Re:How to write PureScript react components to replace JavaS... by chvid on Thursday June 25, 2020 @11:27AM (#23641795)
The code I wrote is perfectly fine. There is no possibility of race conditions in the code I wrote.
Re:How to write PureScript react components to replace JavaS... by Cthulhu_ on Thursday June 25, 2020 @04:24AM (#23638200)
Pedantic and what always happens when someone posts code on the internet, but, I'd extract the onClick function and provide a default value for the onclick parameter for readability, and use cleverness to show off:

    export const Counter = ({label, counterType, onClick}) => {
        const [counter, setCounter] = useState(0);
        onClick = onClick || () => {};
        const handleClick = () => {
          const modifier = counterType === "Increment" ? 1 : -1;
          setCounter(counter + modifier);
          onClick();
        }
        return (
            <button onClick={handleClick}>
                {label}: {counter}
            </button>
        );
    }
There's another commenter that uses Typescript, but I believe PropTypes (https://www.npmjs.com/package/prop-types) are still viable as well - although it moves the checking from compile-time to runtime. I do believe VS Code and co can interpret PropTypes to provide in-editor hints though. And JSDoc as well.
Re:How to write PureScript react components to replace JavaS... by Softcadbury on Thursday June 25, 2020 @04:40AM (#23638312)
You should also use useCallback for handleClick
Re:How to write PureScript react components to replace JavaS... by acemarke on Thursday June 25, 2020 @11:38AM (#23641897)
Not in this example, no. There's zero benefit to memoizing a callback that's passed to a "leaf/host" element like a `<button`>

See my extensive post "A (Mostly) Complete Guide to React Rendering) for details:

https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-...

Re:How to write PureScript react components to replace JavaS... by johnrackles on Thursday June 25, 2020 @07:55AM (#23639580)
Can you explain why? I don't think I've ever used useCallback and certainly not for this type of functionality. I'd love to learn
Re:How to write PureScript react components to replace JavaS... by neolefty on Thursday June 25, 2020 @08:32AM (#23639898)
useCallback memoizes (caches) the function definition. Its main use is to simplify refreshes — since the function isn't redefined every time, components that depend on it such as the <button> can be re-rendered less often.

    const handleClick = useCallback(() => {
        const modifier = counterType === "Increment" ? 1 : -1
        setCounter(counter + modifier)
        onClick()
    }, [onClick, counter, counterType, modifier])
The array at the end is the list of "dependencies" — whenever one of them changes, the function is re-cached. Compiler checks can catch missing dependencies. You might think, "But that function will be redefined pretty much every time," and in this case that's true, and memoization may not help much. But in bigger trees of components, most redraws will be unrelated to any given element, so those dependencies will rarely change.

useCallback() (and its twin useMemo(), for non-functional values) gets more useful in deeper component trees, where values may be passed down several levels.

Re:How to write PureScript react components to replace JavaS... by untog on Thursday June 25, 2020 @09:09AM (#23640274)
I haven’t really dug into React since Hooks were announced and... wow. Am I reading correctly that you use useCallback to avoid redefining your callback function over and over again?

The surface level ergonomics of JSC and the VDOM are great but good lord does it look painful at a second glance. I’m glad I took svelte for a spin.

Re:How to write PureScript react components to replace JavaS... by evanrelf on Thursday June 25, 2020 @01:47AM (#23637295)
The snippets in the article are not using React with hooks. I imagine it would be more similar to your example if the snippets used purescript-react-basic-hooks[1]

[1]: https://github.com/spicydonuts/purescript-react-basic-hooks

Re:How to write PureScript react components to replace JavaS... by Cthulhu_ on Thursday June 25, 2020 @04:20AM (#23638166)
No, they're using more 'old fashioned' class-based components with state; function-based components using hooks is the modern way of writing React. Less boilerplate, for one.
Re:How to write PureScript react components to replace JavaS... by tbenst on Thursday June 25, 2020 @03:07AM (#23637710)
It’s not react, but author of this post also developed a hooks library for Purescript Halogen: https://github.com/thomashoneyman/purescript-halogen-hooks