我们正在实施拍卖云服务,该服务将根据需要从外部API服务接收订单.每个收到的订单是拍卖的1:1.
我们每天可以有超过2000个订单(拍卖).我们决定使用Microservices + Redux来区分订单和拍卖之间的关注点.
贝娄是每项服务的解释.
外部API
Enternal API只是一个网站,它将订单推送到我们的订单服务,并从我们无法控制的订单服务接收更新.
订购服务
订单有一堆信息(属性),客户端(移动应用程序)使用这些信息来获取决定加入拍卖的信息.例如,这是订单的样子:
{
id: 123,
description: 'Some description',
salePrice: 0,
minPrice: 1000,
openPrice: 500,
status: 'active',
address: 'Some address',
file: '.../some-file.pdf',
client: 'Joe Doe',
notes: 'Some notes',
createdAt: '12345678',
pending: false,
postpone: false,
...moreproperties
}
Run Code Online (Sandbox Code Playgroud)
在订单服务中,服务器可以在拍卖开始前的任何时间通过下面的操作更新订单(地址,名称,openPrice,minPrice,状态等).
{ type: LOAD_ORDERS, orders }
{ type: PEND_ORDER, …Run Code Online (Sandbox Code Playgroud) 使用React,Redux和Thunk的组合,我有以下内容:
actions.js
import $ from 'jquery';
import * as types from '../constants/ActionTypes';
import { API_PATH } from '../constants/Config';
export function coursesLoaded(courses) {
return { type: types.COURSES_LOADED, courses };
}
export function fetchData() {
return (dispatch) => {
return $.getJSON(API_PATH).then((response) => {
dispatch(coursesLoaded(response.result));
});
};
}
Run Code Online (Sandbox Code Playgroud)
reducer.js
import { routerReducer as routing } from 'react-router-redux';
import { combineReducers } from 'redux';
import * as types from '../constants/ActionTypes';
const initialState = {
courses: [],
};
function main(state = initialState, action) {
switch(action.type) …Run Code Online (Sandbox Code Playgroud) 我试图以下列方式将多个动作链接在一起:
A.将用户数据发布到数据库
B.使用发布的数据查询Elasticsearch的结果
(我并行做A和B)
B1.使用ES的结果,从两个表B2查询原始数据库的结果.导航到新页面并更新UI
我现在正在使用thunks来推断我的代码,但我也发现这个异步模式非常冗长:
export function fetchRecipes(request) {
return function(dispatch) {
dispatch(requestRecipes(request))
return fetch(url)
.then(response => response.json())
.then(json => dispatch(receiveRecipes(request, json))
)
}
}
Run Code Online (Sandbox Code Playgroud)
这个,以及"requestRecipes"和"receiveRecipes",因为其他动作创建者似乎只是为了进行一次异步调用.(请求,接收和获取功能)
总结:当你链接2-3个异步动作时,它们的输出相互依赖(我需要在可能的情况下进行宣传),是否有更有效的方法可以不为每个异步调用编写3个函数?
我认为必须要有办法.我是Redux文档的模式匹配,很快就被我正在创建的函数所淹没
非常感谢您的反馈!
在编写redux-thunk函数时,称为thunks,有很多样板可以很容易地被抽象掉.例如,在我们的大多数异步API调用中,我们正在执行以下操作,没有任何副作用:
export const LOGIN_REQUEST = 'my-app/auth/LOGIN_REQUEST';
export const LOGIN_RECIEVE = 'my-app/auth/LOGIN_RECIEVE';
export const LOGIN_FAILURE = 'my-app/auth/LOGIN_FAILURE';
// ... reducer code here
export function login(loginHandle, password) {
return (dispatch, getState, api) => {
dispatch({ type: LOGIN_REQUEST });
api.post('/auth/login', { loginHandle, password }).then(
response => dispatch({ type: LOGIN_RECIEVE, response }),
error => dispatch({ type: LOGIN_FAILURE, error })
);
};
}
Run Code Online (Sandbox Code Playgroud)
简单!虽然因为这涵盖了我们至少70%的请求,但我确信有一种优雅的方法可以将上述代码抽象为类似的东西(伪代码):
export function login(loginHandle, password) {
return (dispatch, getState, api) => api('POST', LOGIN_REQUEST, '/auth/login', { loginHandle, password }); …Run Code Online (Sandbox Code Playgroud) 我刚刚开始学习flowtype,我需要一些帮助来理解我脑子里不清楚的两件事.
以https://github.com/reactjs/redux/blob/master/examples/todos-flow为例,我想知道如果没有https://github.com/flowtype/flow-的类型定义,对类型的控制是如何工作的键入,在这种情况下:https://github.com/flowtype/flow-typed/blob/master/definitions/npm/redux_v3.xx/flow_v0.33.x-/redux_v3.xxjs?
如果我使用redux定义,bindActionCreators当我尝试绑定异步动作创建器时,验证失败(我正在使用redux-thunk).
使用redux-thunk时如何继续使用flow并绑定异步操作创建器?
代码示例(https://gist.github.com/momsse/323c228e8c5e264067039b8446cd890f):
import { bindActionCreators } from 'redux';
import type { Dispatch } from 'redux';
type Action = { type: 'SET_PROFILE', profile: Object };
/**
* Based on https://github.com/gaearon/redux-thunk/blob/master/index.d.ts
*/
type ThunkAction = (dispatch: Dispatch<Action>,
getState: () => any,
extraArgument: any) => any;
type Profile = {
name: string,
team: string
}
// Async actions creator
function setProfile(profile: Profile): ThunkAction {
return dispatch …Run Code Online (Sandbox Code Playgroud) 我有以下Redux动作创建者:
export const keyDown = key => (dispatch, getState) => {
const { modifier } = getState().data;
dispatch({ type: KEYDOWN, key });
return handle(modifier, key); // Returns true or false
};
Run Code Online (Sandbox Code Playgroud)
以下连接组件:
export const mapDispatchToProps = dispatch => ({
onKeyDown: e => {
if(e.target.tagName === "INPUT") return;
const handledKey = dispatch(keyDown(e.keyCode));
if(handledKey) {
e.preventDefault();
}
}
});
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个测试,以确保在除了之外的任何操作时dispatch调用该keyDown操作.这是我的测试:tagName"INPUT"
import { spy } from "sinon";
import keycode from "keycodes";
import { mapDispatchToProps } from "./connected-component"; …Run Code Online (Sandbox Code Playgroud) 我在我的项目中使用 redux-saga。我之前使用过 redux-thunk,所以我不能 setState 结束一些异步请求。喜欢
this.props.thunkAsync()
.then(){
this.setState({ '' });
}
Run Code Online (Sandbox Code Playgroud)
由于 thunk 返回 promise,我可以使用“then”。但我不能用 saga 做到这一点,因为 saga 不返回承诺。因此,我通过检查标志道具(如 REQUEST_SUCCESS、REQUEST_WAITING...)在 componentWillReceiveProps 中进行了更改。我认为这不是解决这个问题的好方法。
所以..我的问题是当异步请求以 redux-saga 结束时我该如何做一些工作!
我有几个Redux-Thunk风格的函数,可以在一个文件中调度其他操作.其中一个动作将另一个作为其逻辑的一部分发送.它看起来类似于:
export const functionToMock = () => async (dispatch) => {
await dispatch({ type: 'a basic action' });
};
export const functionToTest = () => async (dispatch) => {
dispatch(functionToMock());
};
Run Code Online (Sandbox Code Playgroud)
在我实际遇到的情况下,函数更加复杂,并且每个函数都分派多个动作对象.结果,当我测试我的现实世界时functionToTest,我想模仿我的现实世界functionToMock.我们已经进行了functionToMock广泛的测试,我不想在这些测试中重复逻辑functionToTest.
但是,当我尝试这样的时候,就像这样:
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
jest.mock('../exampleActions');
const actions = require('../exampleActions');
const mockStore = configureMockStore([thunk]);
describe('example scenario showing my problem', () => {
test('functionToTest dispatches fuctionToMock', () => {
actions.functionToMock.mockReturnValue(() => Promise.resolve());
const store = mockStore({});
store.dispatch(actions.functionToTest()); …Run Code Online (Sandbox Code Playgroud) 我已经React和我一起工作Redux了大约3年.我也redux-thunk用于异步的东西.
而且我非常喜欢它们,但最近我注意到我项目中几乎所有的鸭子都使用相同的动作,减速器,选择器等结构.
例如 - 您有一个应用程序,它有一些用户和事务(或类似)列表,项目详细信息和编辑功能.所有这些列表或项目都有自己的鸭子(动作,减少器,选择器等).
下面的代码将更清楚地显示问题:
// ACTIONS
const const setUser = user => ({
type: types.SET_USER,
payload: user,
});
const cleanUser = () => ({ type: types.CLEAN_USER });
const fetchUser = userId => dispatch =>
dispatch(fetchApi(userRequests.get(userId)))
.then(response => dispatch(setUser(response)))
.catch(error => showNotification(error));
// delete, update, etc... user actions
// REDUCER
const userReducer = (state = null, action) => {
switch (action.type) {
case types.SET_GROUP_ITEM:
return action.payload;
case types.CLEAN_GROUP_ITEM:
return null;
default:
return state; …Run Code Online (Sandbox Code Playgroud) 我在 Next.js 应用程序中使用 RTK(redux-toolkit)。我正在尝试在“getInitialProps”内调度 AsyncThunk Action。在搜索时,我发现了一个名为“next-redux-wrapper”的包,它公开了“getInitialProps”内的“store”,但我正在努力弄清楚如何使其与我的项目一起使用。
这是该项目的准系统示例,我目前正在使用带有 2 个减速器的 Typescript。一种减速器使用 AsyncThunk 从 API 获取数据。我已经安装了“next-redux-wrapper”,但我不知道如何实现它,以便所有页面都可以访问“getInitialProps”内的“store”。该包的文档有一个示例,但相当令人困惑。
这是我的 store.ts 的样子......
import { Action, configureStore, ThunkAction } from '@reduxjs/toolkit';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';
import { counterReducer } from '../features/counter';
import { kanyeReducer } from '../features/kanye';
export const store = configureStore({
reducer: {
counter: counterReducer,
kanyeQuote: kanyeReducer,
},
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string> …Run Code Online (Sandbox Code Playgroud) redux ×10
redux-thunk ×10
javascript ×5
reactjs ×5
react-redux ×2
redux-saga ×2
flowtype ×1
jest ×1
mocking ×1
next.js ×1
sinon ×1
typescript ×1