Skip to content

Instantly share code, notes, and snippets.

@marksteve
Forked from rstacruz/_redux.ex
Last active June 4, 2016 03:38
Show Gist options
  • Save marksteve/79f3cc24119187e75c5ed5c1c5a5f678 to your computer and use it in GitHub Desktop.
Save marksteve/79f3cc24119187e75c5ed5c1c5a5f678 to your computer and use it in GitHub Desktop.
Redux.ex (elixir)
defmodule Redux do
@moduledoc """
Like redux.js, but more elixir-like
store = create_store fn state, action -> ... end
store |> get_state()
store |> dispatch(%{ type: "publish" })
"""
defstruct reducer: nil, state: nil, subscribers: []
@doc """
Creates a store
"""
def create_store(reducer, initial_state \\ nil) do
%Redux{reducer: reducer, state: initial_state}
|> dispatch(%{ type: :"@@redux/INIT" })
end
@doc """
Returns the current state
"""
def get_state(store) do
store.state
end
@doc """
Dispatches an action
"""
def dispatch(store, action) do
store
|> Map.put(:state, store.reducer.(get_state(store), action))
|> run_subscribers(store.subscribers)
end
defp run_subscribers(store, [subscriber | subscribers]) do
subscriber.(store)
run_subscribers(store, subscribers)
end
defp run_subscribers(store, []), do: store
@doc """
Subscribe to a store
"""
def subscribe(store, subscriber) do
unsubscribe = fn(store) -> Map.put(store, :subscribers, store.subscribers -- [subscriber]) end
store = store
|> Map.put(:subscribers, store.subscribers ++ [subscriber])
{unsubscribe, store}
end
end
defmodule Example do
import Redux
def reducer(state, action) do
case action.type do
:set ->
action.value
:add ->
state + action.value
_ ->
state
end
end
def subscriber(store) do
state = get_state(store)
IO.puts("subscriber: #{state}")
end
def another_subscriber(store) do
state = get_state(store)
IO.puts("another_subscriber: #{state}")
end
@doc """
Expected output:
2
subscriber: 12
subscriber: 32
another_subscriber: 32
subscriber: 42
"""
def run do
store = create_store(&reducer/2)
store = store |> dispatch(%{ type: :set, value: 2 })
IO.puts(store |> get_state())
{_, store} = store |> subscribe(&subscriber/1)
store = store |> dispatch(%{ type: :add, value: 10 })
{unsubscribe, store} = store |> subscribe(&another_subscriber/1)
store = store |> dispatch(%{ type: :add, value: 20 })
store = store |> unsubscribe.()
store = store |> dispatch(%{ type: :add, value: 10 })
store
end
end
Example.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment