Comments (13)
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.
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.
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.
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.
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.
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.
from purescript-pux.
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.
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.
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.
I think I see what you mean. The update function for composing multiple components requires much less boilerplate with prisms.
from purescript-pux.
from purescript-pux.
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)
- Combinator for adding incremented key attribute HOT 1
- defaultValue prop HOT 1
- Todomvc example doesn't work with React (instead of preact) HOT 1
- Single element children props is not an array with preact HOT 2
- Add react component as property to another react component (Material-UI) HOT 3
- onKey* events should use KeyboardEvent in handlers HOT 2
- Real world examples HOT 2
- Rendering large numbers of elements exceeds maximum call depth HOT 2
- Page refresh on a route results in 404 page not found HOT 1
- Pux.Router can't parse Facebook and Google login redirect query parameter HOT 1
- Permission to submit benchmark HOT 4
- Needs Aff 4.0 upgrade
- Event fires faster than state update
- Memoize doesn't appreciably improve performance HOT 3
- Is Pux still being mantained? HOT 1
- Plans to update for Purescript 0.12? HOT 5
- Release version 13 on pursuit HOT 5
- Starter app includes outdated bower, fails to build
- Starter app fails to build with error "Module Data.Comparison imports itself"
- Website is broken
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from purescript-pux.