steel
steel

Reputation: 12520

Elm 0.17: HTTP request on init

I have followed this blog post to make an HTTP call when I click a button. I would like to load that data on init, like this question asks, but the solutions given there aren't clear enough for me and my slightly different code.

The app update and init code:

init : (Model, Cmd Msg)
init =
  ( initialModel, Cmd.none )

-- UPDATE

type Msg
  = ArticleListMsg ArticleList.Msg

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    ArticleListMsg articleMsg ->
      let (updatedModel, cmd) = ArticleList.update articleMsg model.articleListModel
      in ( { model | articleListModel = updatedModel }, Cmd.map ArticleListMsg cmd )

The ArticleList update code:

module ArticleList exposing (..)

-- UPDATE

type Msg
  = NoOp
  | Fetch
  | FetchSucceed (List Article.Model)
  | FetchFail Http.Error

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    NoOp ->
      (model, Cmd.none)
    Fetch ->
      (model, fetchArticles)
    FetchSucceed articleList ->
      (Model articleList, Cmd.none)
    FetchFail error ->
      case error of
        Http.UnexpectedPayload errorMessage ->
          Debug.log errorMessage
          (model, Cmd.none)
        _ ->
          (model, Cmd.none)

-- HTTP calls

fetchArticles : Cmd Msg
fetchArticles =
  let
    url = "/api/articles"
  in
    Task.perform FetchFail FetchSucceed (Http.get decodeArticleFetch url)

I've tried sending the command on init instead of Cmd.none:

init : (Model, Cmd Msg)
init =
  ( initialModel, ArticleList.Fetch )

But the compiler complains:

The type annotation is saying:

( Model, Cmd Msg )

But I am inferring that the definition has this type:

( Model, ArticleList.Msg )

I've also tried passing the function:

init =
  ( initialModel, ArticleList.fetchArticles )

But the compiler complains:

Cannot find variable `ArticleList.fetchArticles`.

30|   ( initialModel, ArticleList.fetchArticles )
                  ^^^^^^^^^^^^^^^^^^^^^^^^^
`ArticleList` does not expose `fetchArticles`. 

How can I send the correct message to make the HTTP call on init?

Upvotes: 0

Views: 477

Answers (1)

robertjlooby
robertjlooby

Reputation: 7220

Your init should be

init : (Model, Cmd Msg)
init =
  ( initialModel, Cmd.map ArticleListMsg ArticleList.fetchArticles )

ArticleList.fetchArticles has type Cmd ArticleList.Msg. You need to use Cmd.map to map that value to type Cmd Msg using the ArticleListMsg type constructor.

Upvotes: 2

Related Questions