elm - 如何使用 Elm 在多个组件之间共享存储?
问题描述
我有一个包含两个组件的静态页面。
- 标题中的一个显示处理用户首选项/登录和注册的菜单
- 例如,主页中的一个能够显示用户图像列表或有关用户配置文件的表单。
有没有办法在这两个组件之间共享状态(例如 API 的 access_token)?
我可以向每个组件添加端口,这些端口将更新 localStorage 键并将存储发送到其他组件。
但是有没有更好的方法呢?
解决方案
我最终得到的解决方案是使用两个端口:
port saveStore : String -> Cmd msg
port storeChanged : (String -> msg) -> Sub msg
使用解码器和编码器:
serializeStore : AccessToken -> Profile -> Cmd Msg
serializeStore access_token profile =
encodeStore access_token profile
|> saveStore
encodeStore : AccessToken -> Profile -> String
encodeStore access_token profile =
let
encoded =
Encode.object
[ ( "access_token", tokenToString access_token |> Encode.string )
, ( "profile", encodeUserProfile profile )
]
in
Encode.encode 0 encoded
deserializeStore : String -> Maybe Store
deserializeStore =
Decode.decodeString decodeStore >> Result.toMaybe
decodeStore : Decoder Store
decodeStore =
Decode.map2 Store
decodeToken
(Decode.field "profile" decodeProfile)
decodeToken : Decoder AccessToken
decodeToken =
Decode.field "access_token" Decode.string
|> Decode.andThen
(\token ->
stringToToken token
|> Decode.succeed
)
然后我使用它们来同步我的组件存储并在 localStorage 上保留一份副本:
<script src="app.js"></script>
<script>
// The localStorage key to use to store serialized session data
const storeKey = "store";
const headerElement = document.getElementById("header-app");
const headerApp = Elm.Header.init({
node: element,
flags: {
rawStore: localStorage[storeKey] || ""
}
});
const contentElement = document.getElementById("content-app");
const contentApp = Elm.Content.init({
node: element,
flags: {
rawStore: localStorage[storeKey] || ""
}
});
headerApp.ports.saveStore.subscribe((rawStore) => {
localStorage[storeKey] = rawStore;
contentApp.ports.storeChanged.send(rawStore);
});
contentApp.ports.saveStore.subscribe((rawStore) => {
localStorage[storeKey] = rawStore;
headerApp.ports.storeChanged.send(rawStore);
});
// Ensure session is refreshed when it changes in another tab/window
window.addEventListener("storage", (event) => {
if (event.storageArea === localStorage && event.key === storeKey) {
headerApp.ports.storeChanged.send(event.newValue);
contentApp.ports.storeChanged.send(event.newValue);
}
}, false);
</script>
推荐阅读
- raspberry-pi - 通过 wvdial 发送短信失败(无运营商!重试)
- controller - Strapi beta - 从其他控制器更新其他表
- wpf - 有什么方法可以移植 WPF 应用程序以便它可以在 mac-OS X 上运行?
- java - 为什么 selenium 测试用例在 windows cmd 中运行 testng.xml 时被随机跳过
- xamarin - 如何在后面的代码中为框架设置高度请求?
- c# - 对于某些用户,长时间 ASP.Net 操作超时
- javascript - 错误:0:147:'xFromT':找不到匹配的重载函数
- java - 如果我只在 Spring Boot 中返回 Java 实例数组,则 http 响应正文中有一个空数组
- java - 如何防止 double 舍入到小数点后两位
- android - 带网络连接的 Android 后台服务