Hi all
I am playing with a weather forecast LiveView (just a hobby project to learn elixir on something that looks realistic). The list of days I want to display is certainly ordered.
Fetching weather takes a HTTP call which can fail, so I display a list of day weather rectangles with just “Loading…” and update them asynchronously: when weather fetch result arrives, I update the weather info rectangle for the day.
def handle_event("fetch-weather-click", _, %{assigns: %{target_date: target_date}} = socket) do
weather_elem1 = %{
state: :loading,
date: target_date,
day_weather: nil #real weather info will be sitting here
}
weatherRow = [
weather_elem1
## and more-more-more elements here for the whole week
]
socket = assign(socket,
:weatherRow, weatherRow
)
send(self(), {:fetch_weather, weather_elem1.date})
# and some more similar sends for the other days in the list
{:noreply, socket}
end
def handle_info({:fetch_weather, date}, socket) do
# MyWeatherApi initiates an HTTP call and returns a parsed result
{:ok, dayWeather} = MyWeatherApi.get_weather(date)
weather_elem = %{
state: :known,
date: date,
day_weather: dayWeather
}
# now I need to iterate socket.weatherRow, find element with the date API provided
# replace it's state (or whole element via List.replace_at) and assign it back
socket = assign(socket,
:weatherRow, weatherRow
)
{:noreply, socket}
end
Notice how I need to iterate the list to find an element to be modified, then I need to modify element or replace_at and return a fresh row to the socket. That is all doable and would probably be even natural e.g. in Java arrays, but given immutable lists in Elixir that sounds like a lot of data recreation and slow access by index.
What would be an elixir way for such “find in a list and update”?
Or am I approaching the whole thing wrong?
Maybe there are some other structures for it for such “ordered maps” (to access by key, but maintain an order when rendering)?