tl;dr:我需要一个异步 redux-thunk 操作的示例来展示如何进行异步调用(例如fetch
),并触发状态更新。我还需要看看有人如何将多个此类操作链接在一起,例如:(1)查看用户是否存在于云中,然后(2)如果不存在,则注册它们,然后(3)使用新的用户记录来获取更多数据。
我发现的所有示例都假设 redux 存储可以直接导入到定义操作的模块中。我的理解是这是一个不好的做法:调用组件负责提供对存储的访问,via this.props.dispatch
(来自通过 注入的存储<Provider>
)。
相反,redux 世界中的每个动作都应该返回一个函数,该函数将接收适当的dispatch
; 该功能应该完成工作,并返回......一些东西。Obv,重要的是什么。
这是我根据文档尝试过的模式,但事实证明这是失败的。文档中的任何内容都没有明确说明为什么这不起作用,但事实并非如此——因为此操作不会返回承诺。
/**
* pushes a new user into the cloud; once complete, updates the store with the new user row
* @param {hash} user - of .firstName, .lastName
* @return {promise} resolves with user { userId, firstName, lastName, dateCreated }, or rejects with error
*/
Actions.registerUser = function(user) {
return function reduxAction(dispatch) {
return API.createUser(user) // API.createUser just does return fetch(...)
.then(function onUserRegistered(newUser) {
return dispatch({
type: 'ADD_USERS',
users: [newUser]
});
});
};
};
我有一个响应ADD_USERS
事件的减速器;它将一个或多个用户的传入数组与内存中的用户数组合并。减速器很容易编写。这就是我切换到 redux 的原因:一个商店,纯函数。但这种笨拙的生意绝对是一场噩梦。
我收到的错误.then
是未定义的Actions.registerUser
- 即Actions.registerUser
不返回承诺。
我认为问题显然是我要返回一个函数——reduxAction
函数——但这似乎没有商量余地。在商店拍摄数据的唯一方法是使用dispatch
提供的方法,这意味着我无法返回承诺。
将 更改onUserRegistered
为简单地调用调度然后返回所需的值也不起作用,也不让它返回一个实际的承诺。
请停止。我真的不明白。我不敢相信人们能忍受这一切。
编辑:为了提供一些上下文,这是我认为我应该能够执行的那种动作组合,而这些 thunk 动作令人沮丧:
Actions.bootSetup = function() {
return dispatch => {
return Actions.loadUserId() // looks for userId in local storage, or generates a new value
.then(Actions.storeUserId) // pushes userId into local storage
.then((userId) => {
return Actions.fetchUsers(userId) // fetches the user, by id, from the cloud
.then((user) => {
// if necessary, pushes the user into the cloud, too
return user || Actions.postUser({ userId: userId, firstName: 'auto-registered', lastName: 'tbd'});
});
})
.then((user) => {
console.log(`boot sequence complete with user `, user);
return dispatch({ type: 'ADD_OWNER', user });
});
};
};
我希望这样做,Actions.storeUserId
并且Actions.fetchUsers
除了返回以我选择的值解决的承诺之外,还会将数据发送到商店作为副作用。我认为调度正在发生,但是链条中断了,因为这些动作都没有返回承诺——它们返回普通函数。
这不仅看起来比 Flux 差很多,而且似乎难以理解。我无法相信所有这些疯狂只是为了将应用程序状态整合到一个单一的减少商店中。
是的——我已经尝试了新版本的flux,它带有ReducerStore,但是它对与react-native不兼容的CSS库有一些不适当的依赖。项目维护者表示他们不打算解决这个问题。我猜他们的状态容器依赖于 CSS 功能。
编辑:我的商店
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import Reducers from './reducers';
const createStoreWithMiddleWare = applyMiddleware(thunk)(createStore);
export const initialState = {
users: [] // will hold array of user objects
};
const store = createStoreWithMiddleWare(Reducers);
export default store;
编辑:这是调用代码。这是根级别的 react-native 组件。
// index.ios.js
import Store from './store';
class myApp extends Component {
componentDidMount() {
Store.dispatch(Actions.bootSetup())
.then(() => {
console.log('*** boot complete ***');
});
}
render() {
return (
<Provider store={Store}>
<ApplicationRoutes />
</Provider>
);
}
}
我的假设是Store.dispatch
期望一个函数,并为它提供对商店调度方法的引用。