reactjs - 带有反应钩子的值流
问题描述
我有X
来自服务器的价值。我想公开一个类似于
interface Xclient {
getX(): Promise<X>
}
我稍后将在我的反应功能组件中使用它。
我说类似是因为在幕后我希望它:
- 存储的第一个返回值(它的反应原生)
- 同时为更新版本的 X 发送网络调用,并在我得到响应后重新渲染组件
所以而不是Promise
我可能需要Observable
. 但是那么如何将它与一般反应和特别反应钩子一起使用呢?
我来自后端背景,所以可能有一些我不知道的更规范的方法。如果可能的话我真的不想用redux
!
解决方案
如果我理解正确,您有两个数据源(本地存储和您的 api),并且您想从本地存储中获取价值,然后从 api 中获取实际价值。所以,你应该做下一个:
import { useState } from "react";
const localProvider: Xclient = new Something();
const apiProvider: Xclient = new SomethingElse();
export function SimpleView() {
const [state, setState] = useState("default value");
localProvider()
.then((response) => {
setState(response);
apiProvider()
.then((actualResponse) => {
setState(actualResponse);
})
.catch(/* */);
})
.catch(/* */);
}
但我认为没有理由同步调用它,您可以希望并行运行它:
import { useState } from "react";
const localProvider: Xclient = new Something();
const apiProvider: Xclient = new SomethingElse();
export function SimpleView() {
const [state, setState] = useState("default value");
localProvider()
.then((response) => {
setState(response);
})
.catch(/* */);
apiProvider()
.then((actualResponse) => {
setState(actualResponse);
})
.catch(/* */);
}
如果你想封装这个逻辑,你可以做一个这样的函数:
import { useState } from "react";
const localProvider: Xclient = new Something();
const apiProvider: Xclient = new SomethingElse();
function getValue(localProvider, apiProvider, consumer) {
localProvider()
.then((response) => {
consumer(response);
})
.catch(/* */);
apiProvider()
.then((actualResponse) => {
consumer(actualResponse);
})
.catch(/* */);
}
export function SimpleView() {
const [state, setState] = useState("default value");
getValue(localProvider, apiProvider, setState);
}
UPD: 正如@PatrickRoberts 正确注意到我的示例包含竞争条件,此代码解决了它:
import { useState } from "react";
const localProvider: Xclient = new Something();
const apiProvider: Xclient = new SomethingElse();
function getValue(localProvider, apiProvider, consumer) {
let wasApiResolved = false;
localProvider()
.then((response) => {
if (!wasApiResolved) {
consumer(response);
}
})
.catch(/* */);
apiProvider()
.then((actualResponse) => {
wasApiResolved = true;
consumer(actualResponse);
})
.catch(/* */);
}
export function SimpleView() {
const [state, setState] = useState("default value");
getValue(localProvider, apiProvider, setState);
}
推荐阅读
- flutter - 如何在颤动中单击(关闭)按钮时关闭抽屉?
- java - 是否有任何用于 Spring Boot 的 Maven 任务与 Intelij Idea 的“运行应用程序”的工作方式相同?
- vue.js - 如何使用 vue-analytics 发送虚拟浏览量?
- clojure - go 宏对用户代码做了什么转换?
- java - java.io.FileNotFoundException: 类路径资源 [WEB-INF/dispatcher-servlet.xml] 无法打开,因为它不存在时它确实存在
- jquery - 通过更改 URL 加载部分视图
- vb.net - 我在 Visual basic 中使用随机方程生成器遇到的麻烦比我想象的要多
- java - Jackson Mixin Deserializer 不调用 Setter
- cypress - 如何处理柏树中的新标签。如果子域是动态的?
- node.js - 生成 oauth 访问令牌后,如何使用 pass 访问令牌在 Jira Server 中使用 Rest Api。使用 Nodejs(请求库)