Redux - как вызвать действие и дождаться его разрешения

Я использую response native + redux + redux-thunk, у меня нет большого опыта работы с redux и реагирую на родной

Я вызываю действие внутри своего компонента.

this.props.checkClient(cliente);

if(this.props.clienteIsValid){
   ...
}

и внутри этого действия есть вызов api, который занимает несколько секунд.

export const checkClient = (cliente) => {
    return dispatch => {

        axios.get(`${API_HOST}/api/checkclient`, header).then(response => {

            dispatch({type: CHECK_CLIENT, payload: response.data }); //valid or invalid

        }).catch((error) => {  });

    }
}

Мой вопрос: как я могу отложить возврат действия до завершения ответа api? Мне нужен ответ api, чтобы узнать, действительный ли клиент или недействительный. То есть мне нужно, чтобы действие было разрешено, а затем проверялось, является ли клиент действительным или недействительным.


person Jobsdev    schedule 05.01.2019    source источник


Ответы (3)


Вы можете вернуть обещание из действия, чтобы вызов стал доступным:

// Action
export const checkClient = (cliente) => {
    return dispatch => {
        // Return the promise
        return axios.get(...).then(res => {
            ...
            // Return something
            return true;
        }).catch((error) => {  });
    }
}


class MyComponent extends React.Component {

    // Example
    componentDidMount() {
        this.props.checkClient(cliente)
            .then(result => {
                // The checkClient call is now done!
                console.log(`success: ${result}`);

                // Do something
            })
    }
}

// Connect and bind the action creators
export default connect(null, { checkClient })(MyComponent);

Это может выходить за рамки вопроса, но если хотите, вы можете использовать async await вместо then для обработки вашего обещания:

async componentDidMount() {
    try {
        const result = await this.props.checkClient(cliente);
        // The checkClient call is now done!
        console.log(`success: ${result}`)

        // Do something
    } catch (err) {
        ...
    }
}

Это то же самое.

person micnil    schedule 05.01.2019
comment
Я получаю неопределенный результат. Почему не определено @micnil - person ilovejavaAJ; 12.11.2019
comment
@micnil, не могли бы вы сообщить мне, как я могу заставить эту работу работать с помощью функции react hooks useDispatch ()? - person usama; 24.01.2020

Я не понимаю в чем проблема, но, возможно, это поможет

export const checkClient = (cliente) => {
  return dispatch => {
    dispatch({type: CHECK_CLIENT_PENDING });

    axios.get(`${API_HOST}/api/checkclient`, header).then(response => {

        dispatch({type: CHECK_CLIENT, payload: response.data }); //valid or invalid

    }).catch((error) => {  });

   }
}

...


 this.props.checkClient(cliente);

 if(this.props.clienteIsPending){
  ...
 }

 if(this.props.clienteIsValid){
  ...
 }
person Yasin Tazeoglu    schedule 05.01.2019

Я написал полный код, если путаница не исчезла. Обещание должно работать для последовательности вызовов асинхронного действия redux.

Действия

export const buyBread = (args) => {
  return dispatch => {
    return new Promise((resolve, reject) => {

        dispatch({type: BUY_BREAD_LOADING });
        // or any other dispatch event

        // your long running function
       
        dispatch({type: BUY_BREAD_SUCCESS, data: 'I bought the bread'});
        // or any other dispatch event

        // finish the promise event
        resolve();

        // or reject it
        reject();
    
    });
}

export const eatBread = (args) => {
  return dispatch => {
    return new Promise((resolve, reject) => {

        dispatch({type: EAT_BREAD_LOADING });
        // or any other dispatch event

        // your long running function
       
        dispatch({type: EAT_BREAD_SUCCESS, data: 'I ate the bread'});
        // or any other dispatch event

        // finish the promise event
        resolve();

        // or reject it
        reject();
    
    });
}

Редуктор

const initialState = {}
export const actionReducer = (state = initialState, payload) => {
    switch (payload.type) {
        case BUY_BREAD_LOADING:
           return { loading: true };
        case BUY_BREAD_SUCCESS:
           return { loading: false, data: payload.data };
        case EAT_BREAD_LOADING:
           return { loading: true };
        case EAT_BREAD_SUCCESS:
           return { loading: false, data: payload.data };
}

Класс компонента

import React, {Component} from 'react';

class MyComponent extends Component {
    render() {
        return (
            <div>
                <button onClick={()=>{
                    this.props.buyBread().then(result => 
                        this.props.eatBread();
                        // to get some value in result pass argument in resolve() function
                    );
                }}>I am hungry. Feed me</button>
            </div>
        );
    }
}

const mapStateToProps = (state) => ({
    actionReducer: state.actionReducer,
});

const actionCreators = {
    buyBread: buyBread,
    eatBread: eatBread
};

export default connect(mapStateToProps, actionCreators)(MyComponent));
person bikram    schedule 13.03.2021