Code Monkey home page Code Monkey logo

Comments (13)

AlexeyRaga avatar AlexeyRaga commented on June 8, 2024

I see components as composable and reusable pieces of functionality.
An application can be a single component, or can be composed of a number of components.

I personally prefer when components are defined independently (libs or modules) and know nothing about a bigger scope. This is one of the reasons I am somehow disappointed when I see examples like ToDo written in a way:

todo = ....
  where

    toDoList = ....
      where
        toDoItem = ....

because really a list and an item are defined in a very nested contexts, sometimes even using values from the "outer" context in closure. Perhaps it is the same reason I don't like programs written as one giant function: it is much nicer to have smaller functions and then compose them into other small functions and so one.

So I'd rather prefer writing a "list" component, a "subheader" component, a "chart" component and so on. I could then compose them, say, a "subheader" with a "chart" and have a bigger component, which I can use on the page or compose with something else...

from purescript-pux.

alexmingoia avatar alexmingoia commented on June 8, 2024

Does anything in Pux preclude organizing code like this? What's the difference between moving view functions into separate files and "components"?

from purescript-pux.

AlexeyRaga avatar AlexeyRaga commented on June 8, 2024

I think "components" are functions. As soon as they don't know anything about the "outer" world, e.g. are not coupled with a type of "the application state", etc.
A component declares its own contract, "just functions" are often built around existing external contracts.
For example, typically React components declare their own props.

So I would say that components are functions, but functions are not necessarily components :)

I'd love being able to create components which would declare their own signals/events and, perhaps, have their own functional state if needed. I would like to be able to compose these "components" into bigger components which could react to signals/events from their parts and deal with their own functional state, etc.

I am not saying that it is not possible with pux (I didn't play enough with it), but it would be nice to see it reflected in examples.

from purescript-pux.

alexmingoia avatar alexmingoia commented on June 8, 2024

I see what you mean. Are you familiar with components in the Elm app architecture? I'm working on an API for the equivalent in Pux. Should have something tonight or tomorrow.

from purescript-pux.

born2defy avatar born2defy commented on June 8, 2024

Not to intrude on the conversation, but have you taken a look at the way components are built and combined in the Thermite library using lenses and prisms? The nice part about that approach is it avoids the need to manually reconstruct state and action data types every time you wish to include child components. By using lenses and prisms combined with product or sum type constructors, you can essentially build the new top-level types and manage the child delegations all in one line of code.

Such as in this example:

 spec :: Spec _ (Tuple S1 S2) _ (Either A1 A2)
 spec = focus _1 _Left spec1 <> focus _2 _Right spec2 

In Thermite a component (called a spec) is defined by combining a rendering function and an update function (based on a set of actions defined in an action type). Both functions refer to the same explicit state. So in the above example a new component is built which combines the state of the 2 sub components in a Tuple and which combines the 2 sets of actions into an Either. The use of lenses and prisms ensures that the correct child will be called upon to handle rendering each respective piece of state or to update each respective piece of state based on the respective actions.

from purescript-pux.

alexmingoia avatar alexmingoia commented on June 8, 2024

While it might be cumbersome to reconstruct actions one-level deep with Elm-style components, it's an incredibly simple API that supports parent-child communication. As far as I understand, the Thermite or Halogen component approach has no easy way of having parent components respond to child actions, or have a parent override child update functions for particular actions.

from purescript-pux.

born2defy avatar born2defy commented on June 8, 2024

from purescript-pux.

alexmingoia avatar alexmingoia commented on June 8, 2024

You're right. I took a look at Thermite components and they do support parents responding to child actions. However, actions still need to be constructed using a prism and focus when action types do not match. A case expression is still needed. That's no less boilerplate than the Elm approach.

I'm probably thick-headed, but what exactly is the advantage of using prisms to type component actions? I also don't see the point in having components be a Semigroup... You'll always need to determine how two components are rendered in a render function, so being able to componentA <> componentB seems rather useless? I couldn't find any examples of why components need to be semigroups.

from purescript-pux.

born2defy avatar born2defy commented on June 8, 2024

The real advantage with using lenses and prisms is you don't really need to bother typing out a new datatype to combine all the children within a parent. It took a specific example for me to see the power in this approach, but you can easily define generic sum and product type constructors which combine an arbitrary amount of disparate datatypes into one (essentially Tuple or Either types with more than 2 type parameters). Then you just construct the parent type with simple constructors and route them in one line by applying the correct lenses and prisms and appending the results together like in the example I included originally. This avoids having to create new constructors from scratch for every child in a parent and also makes combination simpler and more flexible. The reason for including a monoid instance is that when two components are appended together, the library will simply create a new component which calls render on both components in order, using lenses to provide the correct piece of the parent state. It works the same way for update functions - appending two components will create a new one which will use the given prism to match the parent action to the child which handles it.

The best way to see this in the source code is to examine the interaction between the semigroup instances and the focus function. It essentially allows you to combine different sub components in a general way without having to create a bunch of new custom data types.

from purescript-pux.

alexmingoia avatar alexmingoia commented on June 8, 2024

The real advantage with using lenses and prisms is you don't really need to bother typing out a new datatype to combine all the children within a parent.

Can you point me to any example code demonstrating this? When I look at the Thermite TodoMVC example, the TaskAction type still needs to be reconstructed in the parent data type TaskListAction. I think we may be talking about different things, or I'm missing something obvious.

from purescript-pux.

alexmingoia avatar alexmingoia commented on June 8, 2024

I think I see what you mean. The update function for composing multiple components requires much less boilerplate with prisms.

from purescript-pux.

born2defy avatar born2defy commented on June 8, 2024

from purescript-pux.

alexmingoia avatar alexmingoia commented on June 8, 2024

With v1.0.0, components are modules exporting Action, State, update, and view functions and nested in the same manner as the Elm app architecture. While I am interested in components that are composable using the traditional typeclasses, I think the base should be a simple, straightforward, concise API. I'm closing this for now, but I welcome any detailed proposals for a component API built on Functor, Semigroup, Apply, etc, as long as it plays nicely with the base architecture.

from purescript-pux.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.