reactjs - 在 Redux 的 reducer 中,我可以在全局(模块)范围内设置一个变量吗?
问题描述
这是使用 ReactJS、Redux 和 Redux-thunk。
在里面reducer/get-data.js
,我可以设置一个
let dataFetchingStartTimestamp;
在全球范围内?我想在全局范围内设置它的原因是函数getData()
以块的形式获取数据,所以第一次,假设它获取前 300 条记录(假设 300 条记录可能需要 10 秒),第二次,另外 300 条记录,依此类推,直到达到 6000 条记录。getData()
AJAX 成功后会调用自己。(then
承诺的处理程序)。
当用户更改 UI Dropbox 时,现有getData()
循环应该停止并使用新值重新启动,并且之前发生的 AJAX 不应该将数据置于 Redux 状态。所以这就是为什么当我们有 时dataFetchingStartTimestamp
,我们可以设置它,当它是第一次获取数据时,dataFetchingStartTimestamp
设置为Date.now()
,然后如果用户更改 UI,那么它将是另一个“第一次获取数据” ” 并因此改变dataFetchingStartTimestamp
. 所以在这个函数内部或者reducer里面,如果它看到那个dataFetchingStartTimestamp
和之前的值不一样,那么它什么也不会做。这意味着,只会执行最新的dataFetchingStartTimestamp
操作。
我想要传递这个值的方式是,getData()
在初始 AJAX 之后调用自身时,将 传递dataFetchingStartTimestamp
给自身, as dataFetchingContinuationTimestamp
,所以这个循环将有一个dataFetchingContinuationTimestamp
与 global 进行比较的值dataFetchingStartTimestamp
。
reducer 是如何得到这个值的:它会在第一次的时候,和 redux 状态的 payload 一起getData()
分派一个 a 。所以在reducer中,后面的语句可以检查当前全局是否和Redux状态一样。如果它们不同,则根本不要改变状态。GET_DATA_START
dataFetchingStartTimestamp
case
dataFetchingStartTimestamp
可以做到这一点,或者也许真的有更好的方法来处理它?我们也可以使用
const dataFetchingStartTimestamp = { value: null };
如果我们只允许设置一个常量,但value
将作为全局值。
另一种方法是制作(函数对象)dataFetchingStartTimestamp
的属性。getData
也许这里所谓的 globaldataFetchingStartTimestamp
并不是真正的全局,而是 webpack 打包的作用域的局部变量,或者作为模块内部的局部变量?
解决方案
我希望我能正确理解这个问题,用户输入会导致异步操作调度,所以如果用户输入搜索输入字符a
,然后b
会触发 2 个搜索:a
和ab
. 如果他们以与用户提供输入不同的顺序解决怎么办?ab
搜索在 1 秒后解析并设置状态。搜索在a
1 秒后解析并覆盖ab
. 您的 UI 现在不同步并显示ab
在搜索文本中,但搜索结果为a
(请参阅下面的隐藏示例)
const later = (value) =>
new Promise((resolve) =>
setTimeout(
() => resolve(value),
value.length === 1 ? 2000 : 1000
)
);
const asyncFunction = (setter, value) => {
console.log('starting async with value:', value);
later(value).then((value) => {
console.log('resolved with value:', value);
setter(value);
});
};
const App = () => {
const [result, setResult] = React.useState('');
const onChange = ({ target: { value } }) => {
asyncFunction(setResult, value);
};
return (
<div>
<input type="text" onChange={onChange} />
<h4>Result:{result}</h4>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
以下是解决此问题的方法:
const later = (value) =>
new Promise((resolve) =>
setTimeout(
() => resolve(value),
value.length === 1 ? 2000 : 1000
)
);
const REPLACED = { message: 'REPLACED' };
const resolveLast = (fn) => {
const check = {};
return (...args) => {
const current = {};
check.current = current;
//You could make check.current Data.now() but
// object reference is guaranteed to be unique
return Promise.resolve(fn(...args)).then((resolve) =>
check.current === current
? resolve
: Promise.reject(REPLACED)
);
};
};
const lastLater = resolveLast(later);
const asyncFunction = (setter, value) => {
console.log('starting async with value:', value);
lastLater(value)
.then((value) => {
console.log('resolved with value:', value);
setter(value);
})
.catch((err) =>
err === REPLACED
? console.log(
`request for ${value} replaced with newer request`
)
: Promise.reject(err)
);
};
const App = () => {
const [result, setResult] = React.useState('');
const onChange = ({ target: { value } }) => {
asyncFunction(setResult, value);
};
return (
<div>
<input type="text" onChange={onChange} />
<h4>Result:{result}</h4>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
推荐阅读
- internet-explorer-11 - 用户代理字符串之间的区别
- python - 无法使用 Pandas DataFrame 对象上的循环获得正确的 DataFrame 形状(行*列)
- sql-server - 我可以提高 excel 到 sql 的 powerquery 性能吗?我使用命名范围参数而不是单元格值?
- flutter - 从国家代码中获取本地化的国家名称
- asp.net-core - 当后缀为“Z”时,ASP.NET Core API ISO8601 未在本地时间解析
- matlab - Matlab parfor 中的工人数量
- php - Composer 诊断返回一个我无法弄清楚的 OpenSSL 库错误
- unity3d - 在统一内使用 mrtk v2 上的跟踪功能
- java - Lotus Domino Server 不返回 Java 中的任何视图(getViews 为空)
- c# - X.PagedList.Mvc 和 PagedList 不工作