for more information visit the package's GitHub page
Package contains the following modules:
In Redux, the common pattern is for your UI modules to come paired as a component and a container. The component does the actual html rendering, while the container constructs props
from the applications main state
. You could imagine that looks like this..
// ./greeter/container.js
import Greeter from './component.js'
const mapStateToProps = state => {
name: [
state.firstName,
state.lastName
].join("")
};
export default connect(mapStateToProps, Greeter)
// ./greeter/component.js
export default const ({name}) =>
(<p>{["Hello", name ].join(" ")}</p>)
What the UI component wants is a name to greet, but we need to construct that name from information in state, because the state doesnt just have a thing in it called name.
Personally, I really dont think this component/container pattern is the best way to do things, this repo is really just an experiment. I have met a few people who tried Elm coming from Redux who said they miss the container / component stuff in Redux. This package is for them; to see if what they want is possible in Elm. Its also demonstrate to Redux people a "middle step" between what they are used to an what is normal in Elm.
A
, and the state has something else B
, and so they need a step from B
to A
. They also know that if they want to re-use the component, their A
might sometimes come from a B
and sometimes a C
. For the component to be re-usable, A
has to be a de-coupled thing if its going to be used in different places. Furthermore, if going from B
to A
is sufficiently complicated, then for organizational and clarity reasons alone you should separate things out. However, (0) Re-use of big UI components is the exception, not the norm, and containers in Redux are very much the norm; (1) The complexity of going from B
to A
is usually pretty low, which makes a distinct B -> A
step superfluous; and (2) if you just took this problem head on, without any fore-knowledge of Elm or Redux, the simplest solution would just be to make an ordinary function that goes from B
to A
, not to build this process into your framework.Model
into Html
, but in Redux, developers use things like constructor()
and componentDidMount()
to implement all kinds of logic, including actions, side effects into the DOM, and http requests. In Elm, the view function has a much narrower role that doesnt include such things.There is a module called Html.Provider
and its identical to the standard Html
module, except for a few features:
1. The Html
type in Html.Provider
is Html model msg
, where model
is the data type your components take.
2. Theres Html.Provider.connect
which takes a props -> Html model msg
function and a function that maps model -> props
.
Poke around in the example project in ./src
to see how it works. I tried to copy the Redux naming scheme directly. Heres maybe the clearest example of what this package provides:
Container
module Header.Container
exposing
( container
)
import Header.View exposing (Props)
import Html.Provider as Provider exposing (Html)
import Model exposing (Model)
import Msg exposing (Msg)
mapStateToProps : Model -> Props
mapStateToProps model =
{ greeting =
if String.isEmpty model.name then
"Hello you!"
else
[ "Hello "
, model.name
, "!"
]
|> String.concat
}
container : Html Model Msg
container =
Provider.connect
Header.View.view
mapStateToProps
Component
module Header.View
exposing
( Props
, view
)
import Html.Provider as Html exposing (Html, div, p)
import Model exposing (Model)
import Msg exposing (Msg)
type alias Props =
{ greeting : String }
view : Props -> Html Model Msg
view props =
p
[]
[ Html.text props.greeting ]