在Redux React中的另一个动作中调用一个动作

时间:2019-03-23 06:59:46

标签: reactjs redux

我正在React中学习Redux。我正在使用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 个答案:

答案 0 :(得分:2)

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 />
  }
}

这里是demo

答案 1 :(得分:2)

因此,这需要对具有“副作用”的Redux流程进行非常基本的介绍。

Redux流

  1. [视图]您的视图以各种方式做出反应。
  2. [动作]我们对这些反应创建一个抽象,称为“动作”。
  3. [Dispatcher]此操作已调度到商店。
  4. [Reducer]在商店中,我们用“ reducers”编写了逻辑,这些逻辑可以查看动作并对商店进行操作以更新商店状态。
  5. [状态]此状态已加载到反应状态树上。
  

定义警报!在Redux中,诸如API调用之类的东西称为“边”。   效果。这是因为您正在做一些典型的事情   单向数据流。

enter image description here

希望您已了解此流程。我特别担心您似乎困惑的特定部分。 因此,在您的代码中,您尝试执行此操作。

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

您的代码在这里试图做的是,它正在试图“分发”副作用。错了!

调度几乎总是一个普通的可序列化的旧JS对象。通常,您将具有这样的成见结构。您似乎在另一个其他人获得的地址呼叫中。

{ 
    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

    }
}

您还应该正确设置redux thunk配置,以使其完全起作用。 干杯!

============ EDIT ============

因此,在检查代码库后,您已使用Combine Reducer将多个reducer融合在一起。

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