Используйте async / await в компоненте React - PullRequest
0 голосов
/ 26 апреля 2018

Является ли хорошей практикой использование async / await непосредственно в компоненте React, а затем сохранение результата в хранилище? Например:

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);

Кажется, он более гибкий, чем классический паттерн реагирования / редукса.

1 Ответ

0 голосов
/ 26 апреля 2018

Да, вы можете использовать async / await в реагирующих компонентах. Это не плохая практика Это просто вопрос архитектуры.

Существует множество способов реализации асинхронной логики в приложениях. В небольшом приложении вы можете реализовать асинхронную логику в реагирующих компонентах. Когда ваше приложение вырастет, у вас появятся некоторые проблемы, такие как дублированный код (например, вы хотите получить пользователя из нескольких реагирующих компонентов), составление кода и разбиение кода.

Вы можете использовать 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.

Эта архитектура позволяет получить строгое разделение слоев. Эта архитектура полезна в больших приложениях.

В небольших приложениях можно использовать redux-thunk или написать асинхронную логику в реагирующих компонентах.

...