在React组件中使用async / await

时间:2018-04-26 09:44:59

标签: reactjs redux async-await

在React组件中直接使用async / await然后将结果存储在商店中是一个好习惯吗?例如:

class User extends Component {

    render() {
        return <div>{this.props.user.name}</div>
    }

    componentWillMount() {
        this.getUser();
    }

    async getUser() {
        try {
            const user = await userAction.get();
            this.props.storeUser(user);
        } catch (err) {}
    }
}

const state2props = (state) => ({
    user: state.User.user
});

const dispatch2props = dispatch => ({
    storeUser: (user) => dispatch(userReducer.store(user)),
});

export default connect(state2props, dispatch2props)(User);

它似乎比传统的react / redux模式更灵活。

1 个答案:

答案 0 :(得分:3)

是的,您可以在react组件中使用async / await。这不是一个坏习惯 这只是架构问题。

有很多方法可以在应用程序中实现异步逻辑。在小型应用程序中,您可以在react组件中实现异步逻辑。当您的应用程序成长时,您将遇到一些问题,例如重复代码(例如,您希望在多个反应组件中获取用户),代码组合和代码拆分。

您可以使用redux-thunk https://github.com/gaearon/redux-thunk,redux-saga https://github.com/redux-saga/redux-saga,redux-logic https://github.com/jeffbski/redux-logic或任何其他解决方案。

此外,您可以创建自己的自定义中间件,例如:

const reactions = {};

export const addReactions = signals => {
  reactions = { ...reactions, ...signals };
};

export default (signalMiddleware = ({ getState, dispatch }) => next => action => {
  if (!action.signal) {
    return next(action);
  }

  if (!reactions[action.signal]) {
    throw new Error(`There is no handler for ${action.signal} signal`);
  }

  reactions[action.signal]({ getState, dispatch, payload: action.payload });
});

此类中间件允许您将业务逻辑实现到单独的层中。例如:

import { addReactions } from './path/to/signalMiddleware';

// Describe your Actions for middleware:
const fetchUser = (id) => ({
    signal: 'FETCH_USER',
    payload: id
});

const anotherAction = () => ({
    signal: 'SOME_ANOTHER_ACTION_WITH_USER',
});


// Describe your business logic using middleware:

addReactions({
    FETCH_USER: async ({dispatch}, {id}) => {
        const user = await fetcher.get(id);
        dispatch({
            type: 'RECEIVE_USER',
            payload: user,
        });
    },
    SOME_ANOTHER_ACTION_WITH_USER: () => {
       // do some awesone job :)
    }
}) 

所以我们的反应成分可能是:

class User extends Component {

    render() {
        return <div>{this.props.user.name}</div>
    }

    componentDidMount() {
       this.props.dispatch(fetchUser(123));
    }   
}

export default connect(state2props, dispatch2props)(User);

现在,您可以将应用程序架构划分为3层:

1)查看 - 反应组件

2)业务逻辑 - 您的中间件

3)数据逻辑 - 你的减速器

在视图和业务层之间,我们使用signal字段和没有type字段的特定操作。 在业务和数据逻辑之间,我们使用type字段的操作。

此架构允许您严格分离图层。该架构在大型应用程序中很有用。

在小型应用程序中,可以在react-components中使用redux-thunk或write async logic。