调用update后命令未触发:Elm导航路由数据获取问题
Hey there! Let's break down how to handle fetching extra data when navigating to your CategoryRoute in Elm. The key thing to remember is that commands (like data fetches) should be dispatched from your update function, not the view—since the view is just for rendering based on the current model state.
Here's a step-by-step approach tailored to your setup:
1. Add Messages for Data Fetching
First, extend your Msg type to handle initiating the fetch and processing the result:
type Msg = OnLocationChange Location | UrlChanged Url -- Add these two messages to manage extra data fetching | FetchCategoryExtraData String | CategoryExtraDataFetched (RemoteData.WebData ExtraData) -- ... keep your existing messages
Replace ExtraData with whatever custom type you're using for the additional category details.
2. Update Your Model to Store Extra Data
Add a field to your Model to track the state of the extra data fetch (loading, success, failure, etc.):
type alias Model = { currentRoute : Route , categories : RemoteData.WebData (List Category) -- Add this line to hold extra category data , categoryExtraData : RemoteData.WebData ExtraData -- ... keep your existing fields }
Initialize this field with RemoteData.NotAsked in your initial model setup.
3. Trigger the Fetch When Route Changes
In your update function, catch the route change event and dispatch the fetch command if the new route is CategoryRoute:
update : Msg -> Model -> (Model, Cmd Msg) update msg model = case msg of OnLocationChange location -> let newRoute = parseLocation location -- Dispatch fetch command only when navigating to CategoryRoute fetchCmd = case newRoute of CategoryRoute categoryId -> -- Replace with your actual API fetch logic Http.get { url = "/api/categories/" ++ categoryId ++ "/extra" , expect = RemoteData.expectJson CategoryExtraDataFetched extraDataDecoder } _ -> Cmd.none in ( { model | currentRoute = newRoute }, fetchCmd ) -- Update model when extra data fetch completes CategoryExtraDataFetched result -> ( { model | categoryExtraData = result }, Cmd.none ) -- ... handle your other existing messages
This ensures the fetch starts immediately when the user navigates to a category route.
4. Adjust the View to Use the Extra Data
Update your page function to render based on both the category data and the fetched extra data state:
page : Model -> Html Msg page model = case model.categories of RemoteData.Success categories -> case model.currentRoute of CategoryListRoute -> CategoryList.view categories CategoryRoute id -> let maybeCategory = categories |> List.filter (\cat -> cat.id == id) |> List.head in -- Check both category existence and extra data state case (maybeCategory, model.categoryExtraData) of (Just category, RemoteData.Success extraData) -> -- Render full category view with extra data CategoryDetail.view category extraData (Just category, RemoteData.Loading) -> div [] [ text "Loading extra details..." ] (Just category, RemoteData.Failure err) -> div [] [ text ("Oops, failed to load extra details: " ++ Debug.toString err) ] (Nothing, _) -> div [] [ text "Category not found" ] RemoteData.Loading -> div [] [ text "Loading categories..." ] RemoteData.Failure err -> div [] [ text ("Failed to load categories: " ++ Debug.toString err) ] RemoteData.NotAsked -> div [] [ text "Initializing..." ]
Quick Tips:
- If users navigate between multiple categories often, consider using a
Dict String (RemoteData.WebData ExtraData)instead of a singlecategoryExtraDatafield—this lets you cache data for previously viewed categories and avoid redundant fetches. - Double-check that your
parseLocationfunction correctly maps URLs to theCategoryRoute idvariant (as set up in the Elm navigation tutorial).
That should do it! Now when users navigate to a category route, your app will automatically fetch the required extra data and update the view once it's ready.
内容的提问来源于stack exchange,提问作者ronif

