-
-
Save marksteve/79f3cc24119187e75c5ed5c1c5a5f678 to your computer and use it in GitHub Desktop.
Redux.ex (elixir)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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