使用 Promise 中间件为 React-Redux 应用程序添加加载指示器
Posted
技术标签:
【中文标题】使用 Promise 中间件为 React-Redux 应用程序添加加载指示器【英文标题】:Add Loading Indicator for React-Redux app with Promise Middleware 【发布时间】:2017-09-25 11:20:00 【问题描述】:我是反应 redux 的新手。我想在用户按下搜索按钮时添加加载文本,并在数据返回或操作完成时关闭文本。 在正常的异步函数中,我可以在回调之前和之后切换 isLoading 标志。
但是,在我的应用程序中,我正在调度一个返回“类型”和“有效负载”的操作,这是一个承诺。中间件 redux-promise 然后“自动”转换该承诺有效负载并将其发送到减速器。 换句话说,中间件在幕后为 Promise 执行 .then 操作,并为我的 reducer 提供正确的数据。
在这种情况下,我不确定如何将加载文本添加到我的视图中,因为一旦我调用 this.props.getIdByName(this.state.value),我不知道数据何时返回。 对我来说,合乎逻辑的地方是在 reducer 内,因为那是数据返回的时候。但是,我认为这将是一个不好的方法,因为减速器不应该执行这样的任务?
在我的组件中,我的提交具有以下功能
handleSubmit(e)
e.preventDefault();
this.props.getIdByName(this.state.value);
在我的 actions/index.js 文件中,我有以下动作生成器
export function getIdByName(name)
const FIELD = '/characters'
let encodedName = encodeURIComponent(name.trim());
let searchUrl = ROOT_URL + FIELD + '?ts=' + TS + '&apikey=' + PUBLIC_KEY + '&hash=' + HASH + '&name=' + encodedName;
const request = axios.get(searchUrl)
return
type: GET_ID_BY_NAME,
payload: request
在我的 reducers/reducers.jsx 中
export default function (state = INITIAL_STATE, action)
switch (action.type)
case GET_ID_BY_NAME:
console.log(action.payload.data.data.results[0].id); <-- here the data comes back correctly because reduer called the promise and gave back the data for me
return ...state, id: action.payload.data.data.results[0].id;
default:
return state;
在我的主 index.js 文件中,我使用以下中间件创建了商店
const createStoreWithMiddleware = applyMiddleware(
promise,
thunk
)(createStore);
【问题讨论】:
【参考方案1】:当您在使用redux-promise
时以Promise
作为其有效负载分派操作时,redux-promise
中间件将捕获该操作,等到Promise
解析或拒绝,然后重新分派该操作,现在使用Promise
的结果作为其有效负载。这意味着您仍然可以处理您的操作,并且一旦您处理它,您就知道它已经完成了。所以你是对的,reducer 是处理这个问题的正确地方。
不过,你说得对,reducer 不应该有副作用。他们应该只建立新的状态。因此,答案是通过在 Redux 中更改应用程序的状态来显示和隐藏加载指示器:)
我们可以在我们的 Redux 存储中添加一个名为 isLoading
的标志:
const reducers =
isLoading(state = false, action)
switch (action.type)
case 'START_LOADING':
return true;
case 'GET_ID_BY_NAME':
return false;
default:
return state;
,
// ... add the reducers for the rest of your state here
export default combineReducers(reducers);
无论何时你要调用getIdByName
,在调用它之前调度一个类型为'START_LOADING'
的动作。当getIdByName
被redux-promise
重新调度时,您将知道加载已完成并且isLoading
标志将设置回false。
现在我们有了一个标志,指示我们是否正在将数据加载到 Redux 存储中。使用该标志,您可以有条件地呈现加载指示器。 :)
【讨论】:
【参考方案2】:我相信 Pedro 的回答应该能让你开始,但我最近在我的应用程序中做了非常准确的 loader/pre-loader
。
最简单的方法是。
-
在您的一个 reducer 中的
state
对象中创建一个新键,并将其命名为 showLoader: false
。
在与之前相同的容器中(带有按钮的容器),创建一个mapStateToProps
并获取该状态属性showLoader
。
在包含您尝试触发loader
的按钮的container
内,添加一个调用action
的onClick
事件,例如displayLoader
。在同一函数中还将this.props.showLoader
设置为true
创建一个displayLoader
操作,编写如下内容:
function displayLoader()
return
type: DISPLAY_LOADER,
payload:
在减速器中,捕获此操作并在收到所需的payload
时将showLoader
设置回false
。
希望对你有帮助!
【讨论】:
以上是关于使用 Promise 中间件为 React-Redux 应用程序添加加载指示器的主要内容,如果未能解决你的问题,请参考以下文章
redux-promise:未捕获的 TypeError:中间件不是函数
REACT 如何使用 Redux 和 Axios(使用 promise 中间件)发出 AJAX 请求?
使用promise和socket.io中间件来实现redux
错误:操作必须是普通对象。相反,实际的类型是:'Promise'。您可能需要添加中间件