Вызов действия в другом действии в Redux React - PullRequest
2 голосов
/ 23 марта 2019

Я изучаю Redux в React. Я использую Redux-Thunk. У меня есть действие, как показано ниже

export const login = (value, history) => dispatch => {
    Axios.post('/api/users/login', value)
        .then(response => {
            dispatch(getAddress()); // I am calling like this
        })
        .catch(error => {});
}

Мое адресное действие, как показано ниже

export const getAddress = () => dispatch => {
    Axios.get('/api/address')
        .then(response => {
            dispatch({
                type: 'getAddresses',
                payload: response.data
            });
        })
        .catch(function (error) {});
}

Я пытаюсь отобразить значение в моем компоненте, как показано ниже

    render() {
        return (
           <div>Hello {console.log(this.props)}</div> // I am getting empty object
        );
    }


const mapStateToProps = state => ({
  addresses: state.address
});

export default connect(mapStateToProps)(Dashboard);

Но я получаю пустой объект.

Я хотел бы перенаправить пользователя на панель мониторинга после входа в систему, где будут отображаться адреса. Как я могу это сделать?

Ответы [ 2 ]

3 голосов
/ 23 марта 2019

Промежуточное программное обеспечение Redux Thunk позволяет соединяться через dispatch, dispatch(...) возвращает отправленное действие, т.е. обещание, если цепочки обещаний не были нарушены:

export const login = (value, history) => dispatch => {
    return Axios.post('/api/users/login', value) // return!
    .then(response => {
        return dispatch(getAddress()); // return!
    })
    .catch(error => {});
}

export const getAddress = () => dispatch => {
    return Axios.get('/api/address') // return!
    .then(response => {
        return dispatch({ // return!
            type: 'getAddresses',
            payload: response.data
        });
    })
    .catch(function (error) {});
}

Начальное действие должно быть отправлено куда-то.В стандартной настройке Redux его можно отправить после определения хранилища:

store.dispatch(login());

В настройке React Redux компоненты являются неотъемлемой частью потока данных Redux.Асинхронный поток является побочным эффектом, и его следует отправлять один раз в componentDidMount.В случае начального действия, оно должно быть отправлено в родительский компонент:

@connect()
class App extends Component {
  componentDidMount() {
    return this.props.dispatch(login());
  }

  render() {
    return !this.props.addresses ? 'Loading' :  <Dashboard />
  }
}

Вот демо .

2 голосов
/ 23 марта 2019

Таким образом, для этого требуется очень простое введение в поток Redux с «побочными эффектами».

Поток Redux

  1. [View] Ваш вид реагирует по-разному.
  2. [Действия] Мы создаем абстракцию над этими реакциями, называемой «действиями».
  3. [Диспетчер] Эти действия отправляются в магазин.
  4. [Редуктор] В магазинеу нас есть логика, написанная на «редукторах», которая просматривает действия и выполняет манипуляции с хранилищем для обновления состояния хранилища.
  5. [State] Это состояние загружается в дерево состояний реакции.

Определение оповещения!В Redux такие вещи, как вызовы API, называются побочными эффектами.Это потому, что вы делаете что-то вне типичного однонаправленного потока данных.

enter image description here

Надеюсь, вы поняли этот поток.Я особенно обеспокоен конкретной частью, в которой вы, кажется, запутались.Итак, в вашем коде вы пытались это сделать.

 then(response => {
     return dispatch(getAddress()); 
 })

То, что ваш код пытается сделать здесь, это то, что он пытается «устранить» побочный эффект.Это неправильно!

Диспетчеризация - это почти всегда простой старый объект JS, который можно сериализировать.Как правило, у вас будет стереотипная структура, как это.Что вы, кажется, имеете в своем другом вызове get get.

{ 
    type: 'GET_ADDRESS_REQUEST_SUCCESS', 
    payload: {} 
}

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

export const login = (value, history) => dispatch => {
    Axios.post('/api/users/login', value)
        .then(response => {
            //Send out a success signal
            dispatch({
                type: 'loginSuccess',
                payload: response.data
            });

            //Now that I have logged in successfully I can call for my address
            //This is simply how you call an action within an action!
            getAddress();
        }).catch(error => {
            //login failed signal
            dispatch({
                type: 'loginFailed',
                payload: response
            }); // I am calling like this
        });
}

export const getAddress = () => dispatch => {
    Axios.get('/api/address')
        .then(response => {
            //Get address success signal
            dispatch({
                type: 'getAddressSuccess',
                payload: response.data
            });
        }).catch(function (error) {
            //Get addresses failed signal
            dispatch({
                type: 'getAddressFailed',
                payload: error
            }); 
        });
}

Следующая важная часть - это редуктор, который вы здесь не включили!Если действия излучают сигналы, думайте о редукторах как о приемнике, который получает и обрабатывает этот сигнал.Редуктор обновит существующее состояние в зависимости от развернутого действия.

export default function appReducer(state, action) {
    switch (action.type) {
        case 'getAddressSuccess': //Waiting on the signal!
            return Object.assign({},state,{address : action.payload} 
            //Set the proper address based on your payload from the api call

        default:
            return state

    }
}

Вы также должны правильно настроить конфигурацию Thunk-редукса, чтобы это полностью работало.Ура!

============ РЕДАКТИРОВАТЬ =============

Так что после проверкиcodebase, вы использовали комбинированный редуктор для объединения нескольких редукторов.

import { combineReducers } from 'redux';
import authReducer from './authReducer';
import addressReducer from './addressReducer';

const rootReducer = combineReducers({
  authReducer,
  addressReducer
});

export default rootReducer;

Итак, в mapsStateToProps состояние вашего магазина будет выглядеть следующим образом

{
  authReducer: {
    // state managed by the authReducer 
  },
  addressReducer: {
    address: 'Test Streat, London'
  }
}

Поэтому измените ваш mapStateToProps так, чтобы он выглядел следующим образом

const mapStateToProps = state => ({
  addresses: state.addressReducer.address
});

export default connect(mapStateToProps)(Dashboard);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...