天道酬勤,学无止境

反应 redux 异步动作创建者测试(React redux async action creator test)

问题

我是 react redux 的新手。 我正在尝试测试异步操作

动作看起来像>

export function fetchUserJd() {
  return (dispatch) => {
    let url = FETCH_JD_ROOT_URL + page + "&" + size;
    dispatch({
      type: REQUEST_INITIATED
    })
    get(url)
      .then((response) => {
        if (response.status === 200) {
          dispatch({
            type: REQUEST_SUCCESSED,
          });
          dispatch({
            type: FETCHING_JOBDESCRIPTION_SUCCESS,
            data: response.payload,
          }
          )
        }
        else {
          dispatch({
            type: REQUEST_SUCCESSED
          })
          toastr.error("Error while fetching Job Description, Please check again");
          if (response.status === "") {
            toastr.error('Our server is down. Please check again');
          }
          dispatch({
            type: FETCHING_JOBDESCRIPTION_FAILED,
            data: response.status,
          });
          if (response.status === 401) {
            toastr.error('Please Login Again');
            localStorage.clear();
            history.push('/');
          }
        }
      })
  }

现在我正在尝试测试它,

describe('Header component actions', () => {

    beforeEach(() => moxios.install());
     afterEach(() => moxios.uninstall());

    it('creates Fetch Jopb description when login action is successful', async (done) => {
        let url = FETCH_JD_ROOT_URL + page + "&" + size;
    moxios.stubRequest(url, {
      status: 201,
      response: mockData.jobDescriptionResponse
    });
    const expectedActions = [{ type: "FETCHING_JOBDESCRIPTION_SUCCESS"}];
    const store = mockStore({});
    await store.dispatch(fetchUserJd())
      .then(() => {
        expect(store.getActions()).toEqual(expectedActions);
      });
    done();
  });
});

所以在这里我得到一个错误,那就是

超时 - 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时内未调用异步回调。

所以,我没有收到此错误,有人可以帮助我吗? 我编写测试用例的方式对吗?

要请求我也使用令牌,

headers: {
                "Authorization": localStorage.getItem("access_token") !== null ? `Bearer ` + localStorage.getItem("access_token") : null,
                "Content-Type": "application/json"
            }

我的呼叫服务就像,

export const get = (url) =>
    axios.get(
        url,
        {
            headers: {
                "Authorization": localStorage.getItem("access_token") !== null ? `Bearer ` + localStorage.getItem("access_token") : null,
                "Content-Type": "application/json"
            }
        }
    ).then(data => {
        if (data.status === HttpStatus.OK) {
            return {
                status: data.status,
                payload: data.data
            };
        }
    }).catch(err => {
        return {
            status: err.response.data,
            payload: null
        };
    });

那么,是不是因为我没有传递令牌?

回答1

你忘了从你的动作创建者那里返回一个Promise :你必须返回get调用,它应该可以工作:

export function fetchUserJd() {
  return (dispatch) => {
    let url = FETCH_JD_ROOT_URL + page + "&" + size;
    dispatch({
      type: REQUEST_INITIATED
    })
    return get(url) // you missed the return statement here
      .then((response) => {
        if (response.status === 200) {
          dispatch({
            type: REQUEST_SUCCESSED,
          });
          dispatch({
            type: FETCHING_JOBDESCRIPTION_SUCCESS,
            data: response.payload,
          }
          )
        }
        else {
          dispatch({
            type: REQUEST_SUCCESSED
          })
          toastr.error("Error while fetching Job Description, Please check again");
          if (response.status === "") {
            toastr.error('Our server is down. Please check again');
          }
          dispatch({
            type: FETCHING_JOBDESCRIPTION_FAILED,
            data: response.status,
          });
          if (response.status === 401) {
            toastr.error('Please Login Again');
            localStorage.clear();
            history.push('/');
          }
        }
      })
  }

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 使用 redux 测试异步操作创建者并做出反应时,无法读取未定义的属性“.then”(Cannot read property '.then' of undefined when testing async action creators with redux and react)
    问题 我正在尝试使用 react、redux-mock-store 和 redux 编写一些测试,但我不断收到错误消息。 也许是因为我的Promise还没有解决? fetchListing()动作创建器在我在开发和生产中尝试时实际上可以工作,但是我在通过测试时遇到了问题。 错误信息 (node:19143) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): SyntaxError (node:19143) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. FAIL src/actions/__tests__/action.test.js ● async actions › creates "FETCH_LISTINGS" when fetching listing has been done TypeError: Cannot read
  • React Redux - 在 Reducer 中添加异步方法是一种反模式吗?(React Redux - Is adding async method in a Reducer an anti pattern?)
    问题 我对整个 react-native/redux 世界还很陌生,所以也许这个问题听起来很愚蠢:) 我知道对于 API 调用或类似的东西,约定是使用中间件,但它总是必要的吗? (它添加了很多样板文件)。 我成功地在减速器中添加了一个异步方法来管理设备 API 连接,例如应用内或本地通知,但我想知道以这种方式处理它是否可以。 例如,在我的减速器中有这个方法: function initInApp(state, itemSkus){ init(state, itemSkus); return { ...state, itemSkus: itemSkus, } } 而这个,管理异步部分: async function init(state, itemSkus){ try { if( !state.isInit ){ const prepare = await Promise.all(RNIap.prepareAndroid()); return{ ...state, isInit: true, errorCode: false, } } else { return ...state; } } catch (errorCode) { return{ ...state, isInit: false, errorCode: errorCode, itemSkus: itemSkus } }
  • 为什么在Redux中我们需要中间件来实现异步流?(Why do we need middleware for async flow in Redux?)
    问题 根据文档,“没有中间件,Redux存储仅支持同步数据流”。 我不明白为什么会这样。 为什么容器组件不能调用异步API,然后dispatch操作? 例如,想象一个简单的UI:一个字段和一个按钮。 当用户按下按钮时,该字段将填充来自远程服务器的数据。 import * as React from 'react'; import * as Redux from 'redux'; import { Provider, connect } from 'react-redux'; const ActionTypes = { STARTED_UPDATING: 'STARTED_UPDATING', UPDATED: 'UPDATED' }; class AsyncApi { static getFieldValue() { const promise = new Promise((resolve) => { setTimeout(() => { resolve(Math.floor(Math.random() * 100)); }, 1000); }); return promise; } } class App extends React.Component { render() { return ( <div> <input value={this.props.field}/>
  • 在 redux 中使用样板操作和减速器(Use of boilerplate actions and reducers in redux)
    问题 我一直在遵循广泛给出的学习 React 开发的建议,首先掌握组件props ,将 UI 状态封装在组件级别this.state并通过组件树有选择地向下传递。 这是一次有启发性的经历。 我开始欣赏无状态视图设计模式的强大功能,并且我觉得我已经能够使用这些技术实现健壮且组织良好的结果。 继续,我现在正在尝试使用redux合并更复杂的状态管理。 但是当我涉足复杂性并将redux集成到我的应用程序中时,我发现自己面临以下关于我的代码如何演变的观察。 其中一些发展似乎是明智的,但其他发展让我怀疑我是否在做“正确”的事情。 1) Action Creator 作为业务和 UI 逻辑的纽带 我发现以前在 React 生命周期函数componentDidUpdate等和onTouch/onPress处理程序中实现的大部分逻辑现在在action creators 中实现。 这似乎是一个积极的发展,因为它使“一切都在同一个地方”并允许进行单元测试。 问题:将业务逻辑集中在相当复杂的动作创建者网络中是最佳实践吗? 2) 空心reducers 作为上面#1 的推论,我发现我的reducers和它们相应的action对象已经演变成一个事实上的 setter 列表,它们只是用传递的值更新状态存储,以这种方式: case types.SAVE_ORDER: return Object.assign({}
  • React Redux 异步动作测试(React Redux async action testing)
    问题 我编写了测试来测试异步操作。 我目前收到以下错误TypeError: Cannot read poperty 'then' of undefined它指向我代码中的以下行 return store.dispatch(actions.fetchMovies()).then(() => { 这是我的代码: 异步操作测试: import { createStore, applyMiddleware } from 'redux'; import initialState from '../reducers/initialState'; import rootReducer from '../reducers/index'; import thunk from 'redux-thunk'; import * as actions from './actions'; import * as ActionTypes from '../constants/constants'; import nock from 'nock'; import { expect } from 'chai'; import API_KEY from '../config/config'; const MOVIES_API = 'https://api.themoviedb.org/3/discover/movie
  • 我应该如何将“redux-thunk”用于异步初始状态? (反应/还原)(How should I use “redux-thunk” for Async Initial state ? (react/redux))
    问题 这个问题已经被问过几次了,但是我并没有真正理解我找到的答案。 使用 React/Redux,我正在尝试使用 express 将异步数据置于我的初始状态。 由于我习惯于 d3,我的选择之一是使用“d3.json”……但如果它更好,我会很乐意使用其他东西。 从之前关于同一主题的答案中,我添加了以下代码: // redux action using a dispatcher (think middleware) export function cool(url) { return function(dispatch) { return d3.json(url, response => { dispatch(setData(response)) } } } // redux action export function setData(data) { return { type: 'DATA_CHART_ALL', data } } const authorDataReducer = (state = {}, action) => { switch (action.type) { case 'DATA_CHART_ALL': return action.data case 'DATA_CHART_FILTER': return action.data default: return
  • 在ES6生成器中使用redux-saga的优点/缺点与在ES2017 async / await中使用redux-thunk的优点/缺点(Pros/cons of using redux-saga with ES6 generators vs redux-thunk with ES2017 async/await)
    问题 现在有很多关于redux镇上最新的孩子redux-saga / redux-saga的话题。 它使用生成器功能来侦听/调度动作。 在开始思考之前,我想知道使用redux-saga的优点/缺点,而不是下面的在异步/等待状态下使用redux-thunk的方法。 组件可能看起来像这样,像往常一样调度动作。 import { login } from 'redux/auth'; class LoginForm extends Component { onClick(e) { e.preventDefault(); const { user, pass } = this.refs; this.props.dispatch(login(user.value, pass.value)); } render() { return (<div> <input type="text" ref="user" /> <input type="password" ref="pass" /> <button onClick={::this.onClick}>Sign In</button> </div>); } } export default connect((state) => ({}))(LoginForm); 然后我的动作如下所示: // auth.js import request from
  • 如何使用超时调度Redux动作?(How to dispatch a Redux action with a timeout?)
    问题 我有一个操作可以更新我的应用程序的通知状态。 通常,此通知将是错误或某种信息。 然后,我需要在5秒钟后分派另一项操作,该操作会将通知状态恢复为初始状态,因此没有通知。 其背后的主要原因是提供了5秒钟后通知自动消失的功能。 我没有使用setTimeout并返回另一个动作的运气,无法找到如何在线完成。 因此,欢迎提出任何建议。 回答1 不要陷入认为图书馆应该规定如何做所有事情的陷阱。 如果要在JavaScript中进行超时操作,则需要使用setTimeout 。 没有理由为什么Redux动作应该有所不同。 Redux确实提供了一些处理异步内容的替代方法,但是只有在意识到重复太多代码时,才应使用这些方法。 除非您有此问题,否则请使用语言提供的内容并寻求最简单的解决方案。 内联编写异步代码 到目前为止,这是最简单的方法。 而且这里没有关于Redux的特定内容。 store.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' }) setTimeout(() => { store.dispatch({ type: 'HIDE_NOTIFICATION' }) }, 5000) 同样,从连接的组件内部: this.props.dispatch({ type: 'SHOW_NOTIFICATION', text:
  • redux 中的业务逻辑放在哪里? 行动或商店(Where to put business logic in redux? action or store)
    问题 我从Reflux到Redux 。 在 Reflux 中,您的业务逻辑仅存在于商店中,但在Redux 中似乎有所不同。例如,在“ Redux ”中,我有“async-action”,并使用“ redux-thunk ”实现了它。 在一种情况下,我想检查我的操作中的某些内容,如果需要,我将请求发送到服务器并获取一些数据。 在这种情况下,我必须在我的操作中检查我的逻辑,实际上我的业务逻辑存在于操作中并存储在一起并且它不好......你的解决方案是什么? 例如,我有复选框,我检查了一些条件,如果结果为真,我向服务器发送请求,这里是我的操作代码,正如您看到的,我的业务逻辑在我的 Action 和我的 Reducer 上: export function onCheckboxClick({itemId}) { return (dispatch, getState) => { let state = getState().get('myReducer'); let myConditionResult = state.get('foods').get(0).get('test');//for exmaple check some condition in my store dispatch({type: 'CHECKBOX_CLICK', itemId});// for change the
  • 在操作 redux 后反应路由器重定向(React router redirect after action redux)
    问题 我正在使用react-redux和react-router 。 我需要在分派动作后重定向。 例如:我注册了几步。 行动后: function registerStep1Success(object) { return { type: REGISTER_STEP1_SUCCESS, status: object.status }; } 我想重定向到带有 registrationStep2 的页面。 我怎样才能做到这一点? ps 在历史浏览器 '/registrationStep2' 中没有被访问过。 此页面仅在结果注册成功后才会出现Step1 页面。 回答1 使用 React Router 2+,无论您在何处发送操作,都可以调用browserHistory.push() (或hashHistory.push()如果您使用的是): import { browserHistory } from 'react-router' // ... this.props.dispatch(registerStep1Success()) browserHistory.push('/registrationStep2') 如果这是您使用的,您也可以从异步动作创建者那里执行此操作。 回答2 你检查过 react-router-redux 吗? 这个库可以将 react-router 与 redux
  • React-Router:如何在路由转换之前等待异步操作(React-Router: how to wait for an async action before route transition)
    问题 是否可以在特定路由上调用称为thunk的异步redux动作,并且在响应成功或失败之前不执行转换? 用例 我们需要从服务器加载数据并用初始值填写表单。 从服务器获取数据之前,这些初始值不存在。 像这样的一些语法会很棒: <Route path="/myForm" component={App} async={dispatch(loadInitialFormValues(formId))}> 回答1 要回答防止在响应成功或失败之前过渡到新路线的原始问题,请执行以下操作: 因为您使用的是redux thunk,所以操作创建者可以成功或失败触发重定向。 我不知道您的特定动作/动作创建者是什么样子,但是这样的方法可能有效: import { browserHistory } from 'react-router' export function loadInitialFormValues(formId) { return function(dispatch) { // hit the API with some function and return a promise: loadInitialValuesReturnPromise(formId) .then(response => { // If request is good update state with fetched
  • React-redux:如何编写集成测试(React-redux: How to write an integration test)
    问题 我正在使用Enzyme来测试我的 react 和 redux 部分。 我已经阅读并发现为组件编写集成测试也是一种很好的做法。 所以,这很简单,因为我必须调用动作创建者并根据存储检查它们的更新值,但我有一些异步动作返回dispatch动作。 登录.actions.js export function loginUser(credentials) { return dispatch => { dispatch(action.loginRequest()); return axios({ method: 'post', url: `${api}/login`, data: { email: _.trim(_.get(credentials, 'email')), password: _.get(credentials, 'password') } }) .then(response => { const { data } = response; if (_.isEqual(_.get(response, 'status'), 200)) { dispatch(action.loginSuccess(data)); } }) .catch(err => { dispatch(action.loginError(err)); }); }; } 登录.actionCreators.js
  • 在 redux 中使用 thunk 中间件比使用常规函数作为异步动作创建者有什么好处? [关闭](What are the benefits of using thunk middleware in redux over using regular functions as async action creators? [closed])
    问题 关闭。 这个问题需要更加集中。 它目前不接受答案。 想改善这个问题吗? 更新问题,使其仅通过编辑这篇文章来关注一个问题。 5年前关闭。 改进这个问题 我已经使用 redux 大约两个月了,最近才开始探索处理异步行为(例如获取数据)的不同方法。 从文档和 GitHub 上的讨论看来,通过使用 thunk 中间件来执行此操作的标准方法是一个非常简单的概念,但是我不确定我是否理解将执行异步状态机的责任交给 redux 的好处当可以使用简单的独立函数时的中间件。 使用 thunk 中间件的传统 Redux 方法 异步操作创建者fetchPosts function fetchPosts(reddit) { return dispatch => { dispatch(requestPosts(reddit)) return fetch(`http://www.reddit.com/r/${reddit}.json`) .then(response => response.json()) .then(json => dispatch(receivePosts(reddit, json))) } } 那么也许在 ReactJS 组件中可能会有一个按钮,如下所示。 调度 fetchPosts <button onClick={() => this.props.dispatch
  • 如何测试仅调度其他操作的 Redux 操作创建器(How do I test a Redux action creator that only dispatches other actions)
    问题 我在测试仅循环传递给它的数组并为该数组中的每个项目分派一个动作的动作创建器时遇到问题。 这很简单,我似乎无法弄清楚。 这是动作创建者: export const fetchAllItems = (topicIds)=>{ return (dispatch)=>{ topicIds.forEach((topicId)=>{ dispatch(fetchItems(topicId)); }); }; }; 这是我尝试测试它的方式: describe('fetchAllItems', ()=>{ it('should dispatch fetchItems actions for each topic id passed to it', ()=>{ const store = mockStore({}); return store.dispatch(fetchAllItems(['1'])) .then(()=>{ const actions = store.getActions(); console.log(actions); //expect... I can figure this out once `actions` returns... }); }); }); 我收到此错误: TypeError: Cannot read property 'then' of
  • 在成功的异步 redux 操作上转换到另一条路线(Transition to another route on successful async redux action)
    问题 我有一组非常简单的反应组件: 挂钩到 redux 并处理操作、存储订阅等的container list显示我的物品列表 new这是一种将新项目添加到列表中的表单 我有一些反应路由器路线如下: <Route name='products' path='products' handler={ProductsContainer}> <Route name='productNew' path='new' handler={ProductNew} /> <DefaultRoute handler={ProductsList} /> </Route> 以便显示list或form ,但不能同时显示两者。 我想要做的是在成功添加新项目后让应用程序重新路由回列表。 到目前为止,我的解决方案是在异步dispatch之后有一个.then() : dispatch(actions.addProduct(product) .then(this.transitionTo('products')) ) 这是执行此操作的正确方法还是我应该以某种方式触发另一个操作以触发路线更改? 回答1 如果你不想使用像 Redux Router 这样更完整的解决方案,你可以使用 Redux History Transitions,它可以让你编写这样的代码: export function login() { return
  • React + Redux,如何不是在每次分派后而是在几次分派后渲染?(React + Redux, How to render not after each dispatch, but after several?)
    问题 我正在尝试对商店进行多项更改,但在完成所有更改之前不会渲染。 我想用 redux-thunk 来做到这一点。 这是我的动作创建者: function addProp(name, value) { return { type:'ADD_PROP', name, value } } function multiGeoChanges(...changes) { // my goal here is to make multiple changes to geo, and make sure that react doesnt update the render till the end return async function(dispatch, getState) { for (let change of changes) { dispatch(change); await promiseTimeout(2000); } } } 我像这样派遣我的异步动作创建者: store.dispatch(multiGeoChanges(addProp(1, "val1"), addProp(2, "val2"), addProp(3, "val3"))); 然而,这会导致在每次dispatch后进行渲染。 我是 redux-thunk 的新手,我从未使用过异步中间件,但我认为它可以帮助我。
  • redux thunk调度后从商店返回promise(return promise from store after redux thunk dispatch)
    问题 我正在尝试与redux thunk链接调度 function simple_action(){ return {type: "SIMPLE_ACTION"} } export function async_action(){ return function(dispatch, getState){ return dispatch(simple_action).then(()=>{...}); } } 我如何获得调度以从商店退还承诺? 进一步来说: 我可能只是在这里不了解某些内容,但是在所有具有redux-thunk的示例中,它们都调用了一个单独的异步事件(例如fetch ),显然它返回了Promise 。 我要寻找的是当我向商店分派一个动作时:如何确定商店在上述函数action_creator()发生任何其他事情之前已完全处理了该动作。 理想情况下,我希望商店返回某种承诺,但我不知道这种情况如何发生或发生在哪里? 回答1 在这里,您有一个有关如何分派和链接异步操作的示例。 https://github.com/gaearon/redux-thunk 笨拙的中间件知道如何将笨拙的异步动作转换为动作,因此您只需要使simple_action()成为笨拙的东西即可,笨拙的中间件将为您完成工作,如果中间件看到正常的动作,他将分派此动作动作作为正常动作,但是如果它是一个异步功能
  • 如何处理 Redux 中复杂的副作用?(How to handle complex side-effects in Redux?)
    问题 我一直在努力寻找这个问题的解决方案...... 我正在开发带有在线记分牌的游戏。 玩家可以随时登录和退出。 完成一场比赛后,玩家会看到计分板,看到自己的排名,分数会自动提交。 记分牌显示玩家的排名和排行榜。 计分板在用户完成游戏(提交分数)和用户只想查看他们的排名时使用。 这就是逻辑变得非常复杂的地方: 如果用户已登录,则将首先提交分数。 保存新记录后,将加载记分板。 否则,记分板将立即加载。 玩家可以选择登录或注册。 之后,将提交分数,然后再次刷新记分板。 但是,如果没有分数提交(只需查看高分表)。 在这种情况下,玩家的现有记录被简单地下载。 但由于此操作不影响计分板,因此应同时下载计分板和玩家的记录。 有无限数量的级别。 每个级别都有不同的记分牌。 当用户查看记分牌时,用户正在“观察”该记分牌。 当它关闭时,用户停止观察它。 用户可以随时登录和注销。 如果用户退出,该用户的排名应该消失,如果用户以另一个账户登录,那么应该获取并显示该账户的排名信息。 ...但是这种获取此信息的操作应该只针对用户当前正在观察的记分板进行。 对于查看操作,结果应该缓存在内存中,这样如果用户重新订阅同一个记分板,就不会获取。 但是,如果有分数正在提交,则不应使用缓存。 任何这些网络操作都可能失败,玩家必须能够重试它们。 这些操作应该是原子的。 所有状态都应该一次性更新(没有中间状态)。 目前
  • 在 Redux 测试中,Nock 没有拦截 API 调用(Nock is not intercepting API call in Redux test)
    问题 我正在尝试在 redux 应用程序中测试 api 调用。 该代码几乎遵循 redux 文档的Async Action Creators部分中概述的模式: http://redux.js.org/docs/recipes/WritingTests.html 它的要点是您使用redux-mock-store来记录和断言触发的任何操作。 这是整个测试,使用 nock 来模拟 api 调用: import React from 'React' import ReactDOM from 'react-dom' import expect from 'expect'; import expectJSX from 'expect-jsx'; import TestUtils from 'react-addons-test-utils' import configureMockStore from 'redux-mock-store' import thunk from 'redux-thunk' import nock from 'nock' expect.extend(expectJSX); import * as types from '../../constants/Actions' describe('Async Search Actions', () => { const
  • 动作必须是 React/Redux 中的普通对象吗?(Actions must be plain Objects in React/Redux?)
    问题 我遇到的问题是,当通过我的动作创建者传递数据时, Actions must be plain objects 。 基本上,我试图通过单击按钮来捕获用户输入,并根据单击的按钮(视图)将event.target.innerHTML传递给动作创建者fetchDataAsync(view) ,然后通过 axios 执行 GET 请求并根据选择的视图进行调度。 不过,我还是 Redux 的新手,我不确定我在这里做错了什么。 我之前见过在动作创建者内部执行的异步动作...... 与 Redux 连接的组件: class ViewSelector extends Component { selectView(event) { this.props.fetchDataAsync(event.target.innerHTML); } render() { return ( <nav> <button onClick={this.selectView.bind(this)}>VIEW ALL</button> <button onClick={this.selectView.bind(this)}>VIEW LAST WEEK</button> <button onClick={this.selectView.bind(this)}>VIEW LAST MONTH</button> </nav>