相关疑难解决方法(0)

为什么我们需要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}/>
                <button disabled={this.props.isWaiting} onClick={this.props.update}>Fetch</button>
                {this.props.isWaiting && <div>Waiting...</div>}
            </div>
        ); …
Run Code Online (Sandbox Code Playgroud)

javascript asynchronous reactjs redux redux-thunk

600
推荐指数
9
解决办法
12万
查看次数

如何处理Redux中复杂的副作用?

我一直在努力寻找解决这个问题的方法......

我正在开发一个带有在线记分牌的游戏.玩家可以随时登录和注销.完成游戏后,玩家将看到记分牌,并查看自己的排名,并自动提交分数.

记分牌显示了玩家的排名和排行榜.

截图

当用户完成播放(提交分数)以及用户只想查看他们的排名时,使用记分板.

这是逻辑变得非常复杂的地方:

  • 如果用户已登录,则将首先提交分数.保存新记录后,将加载记分板.

  • 否则,将立即加载记分板.玩家将获得登录或注册的选项.之后,将提交分数,然后记分板将再次刷新.

  • 但是,如果没有要提交的分数(只需查看高分表).在这种情况下,只需下载播放器的现有记录.但由于此操作不会影响记分牌,因此记分牌和玩家记录应同时下载.

  • 有无限数量的级别.每个级别都有不同的记分牌.当用户查看记分板时,用户正在"观察"该记分板.当它关闭时,用户停止观察它.

  • 用户可以随时登录和注销.如果用户注销,则用户的排名应该消失,如果用户以另一个帐户登录,则应该获取并显示该帐户的排名信息.

    ...但是,此信息只应针对用户当前正在观察的记分板进行.

  • 对于查看操作,结果应缓存在内存中,以便如果用户重新订阅同一记分板,则不会提取.但是,如果提交了分数,则不应使用缓存.

  • 任何这些网络操作都可能失败,并且播放器必须能够重试它们.

  • 这些操作应该是原子的.所有状态都应该一次更新(没有中间状态).

目前,我能够使用Bacon.js(功能性反应式编程库)来解决这个问题,因为它提供了原子更新支持.代码非常简洁,但现在它是一个混乱的不可预测的意大利面条代码.

我开始看Redux.所以我尝试构建商店,并想出了类似的东西(用YAMLish语法):

user: (user information)
record:
  level1:
    status: (loading / completed / error)
    data:   (record data)
    error:  (error / null)
scoreboard:
  level1:
    status: (loading / completed / error)
    data:
      - (record data)
      - (record data)
      - (record data)
    error:  (error / null)
Run Code Online (Sandbox Code Playgroud)

问题变成:我在哪里放置副作用.

对于无副作用的动作,这变得非常容易.例如,在LOGOUT行动时,record减速器可以简单地将所有记录都抛出.

但是,某些行为确实有副作用.例如,如果我在提交分数之前没有登录,那么我成功登录,该SET_USER操作将用户保存到商店中.

但是因为我有一个要提交的分数,这个SET_USER动作也必须引发一个AJAX请求,同时设置record.levelN.statusloading.

问题是:当我以原子方式登录时,我如何表示应该发生副作用(得分提交)

在Elm架构中,更新程序在使用形式时也会发出副作用 …

javascript flux redux

45
推荐指数
2
解决办法
8870
查看次数

Redux Thunk和Redux Saga有什么区别?

Redux Thunk和Redux Saga都是Redux的中间件.两者之间有什么区别以及如何确定何时使用Redux Thunk或Redux Saga?

reactjs redux react-redux

11
推荐指数
2
解决办法
5850
查看次数

减少redux-thunk样板

在编写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)

javascript reactjs redux redux-thunk redux-saga

9
推荐指数
1
解决办法
757
查看次数

如何使用 thunk 在 react-redux 钩子中进行异步调用?

我开始学习钩子。但我不明白如何正确使用异步调用。早些时候我用过

import * as actionQR from "../actions/qr";
...
function mapDispatchToProps(dispatch) {
    return {
        actionQR: bindActionCreators(actionQR, dispatch),
    }
} 
Run Code Online (Sandbox Code Playgroud)

在调用 my 之后this.props.actionQR.myFunc(),我应该用 useDispatch() 做什么?如果我只是打电话

import {foo} from "../actions/qr";
...
useDispatch(foo());
Run Code Online (Sandbox Code Playgroud)

那么我foo()console.log(2)

export const foo = () => {
    console.log(1);
    return (dispatch) => {
        console.log(2);
      }
}
Run Code Online (Sandbox Code Playgroud)

我使用 thunk

import createRootReducer from './reducers/index';
...
const store = createStore(createRootReducer, applyMiddleware(thunk));
Run Code Online (Sandbox Code Playgroud)

reactjs redux redux-thunk react-redux react-hooks

6
推荐指数
1
解决办法
6441
查看次数